From 78aafda47e9f79e29bde84a43b7ed39cf8d09958 Mon Sep 17 00:00:00 2001 From: Gavin Bunney Date: Fri, 11 Oct 2019 15:41:15 -0700 Subject: [PATCH] Added license details to `data.plugin` --- .gitignore | 1 + README.md | 26 +++- bitbucket/data_plugin.go | 229 +++++++++++++++++++++++++++----- bitbucket/data_plugin_test.go | 59 +++++++- scripts/start-docker-compose.sh | 19 ++- 5 files changed, 293 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index e51f2c6..273bbf4 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ website/vendor scripts/gogetcookie.sh docker-compose +docker-compose-test-plugin.jar diff --git a/README.md b/README.md index 84904bf..c2e9243 100644 --- a/README.md +++ b/README.md @@ -530,9 +530,27 @@ data "bitbucketserver_plugin" "myplugin" { * `description` - Plugin description. * `user_installed` - Set to `true` if this is a user installed plugin vs a system bundled plugin. * `optional` - Set to `true` if this is an optional plugin. -* `vendor_name` - Name of the vendor. -* `vendor_link` - Vendor homepage. -* `vendor_marketplace_link` - Plugin marketplace link. +* `vendor.name` - Name of the vendor. +* `vendor.link` - Vendor homepage. +* `vendor.marketplace_link` - Plugin marketplace link. +* `license.0.valid` - Is the license valid. true/false. +* `license.0.evaluation` - Is the license an evaluation. true/false. +* `license.0.nearly_expired` - Is the license nearly expired. true/false. +* `license.0.maintenance_expiry_date` - Date of maintenance expiry. +* `license.0.maintenance_expired` - Is the maintenance expired. true/false. +* `license.0.license_type` - Type of license. +* `license.0.expiry_date` - Expiry date of the license. +* `license.0.raw_license` - The raw license information. +* `license.0.renewable` - Is the license renewabl. true/false. +* `license.0.organization_name` - Name of the organization the license is for. +* `license.0.enterprise` - Is the license for enterprise. true/false. +* `license.0.data_center` - Is the license for data center. true/false. +* `license.0.subscription` - Is the license a subscription. true/false. +* `license.0.active` - Is the license active. true/false. +* `license.0.auto_renewal` - Is the license renewed automatically. true/false. +* `license.0.upgradable` - Is the license able to be upgraded. true/false. +* `license.0.crossgradeable` - Can the license be crossgraded. true/false. +* `license.0.purchase_past_server_cutoff_date` - The purchase date past the server cutoff date. true/false. --- @@ -540,7 +558,7 @@ data "bitbucketserver_plugin" "myplugin" { ### Requirements -- [Terraform](https://www.terraform.io/downloads.html) 0.10.x +- [Terraform](https://www.terraform.io/downloads.html) 0.12.x - [Go](https://golang.org/doc/install) 1.11 (to build the provider plugin) ### Building The Provider diff --git a/bitbucket/data_plugin.go b/bitbucket/data_plugin.go index 9027a84..c65edd7 100644 --- a/bitbucket/data_plugin.go +++ b/bitbucket/data_plugin.go @@ -23,6 +23,29 @@ type Plugin struct { } `json:"vendor,omitempty"` } +type PluginLicense struct { + Valid bool `json:"valid,omitempty"` + Evaluation bool `json:"evaluation,omitempty"` + NearlyExpired bool `json:"nearlyExpired,omitempty"` + MaintenanceExpiryDate jsonTime `json:"maintenanceExpiryDate,omitempty"` + MaintenanceExpired bool `json:"maintenanceExpired,omitempty"` + LicenseType string `json:"licenseType,omitempty"` + ExpiryDate jsonTime `json:"expiryDate,omitempty"` + RawLicense string `json:"rawLicense,omitempty"` + Renewable bool `json:"renewable,omitempty"` + OrganizationName string `json:"organizationName,omitempty"` + ContactEmail string `json:"contactEmail,omitempty"` + Enterprise bool `json:"enterprise,omitempty"` + DataCenter bool `json:"dataCenter,omitempty"` + Subscription bool `json:"subscription,omitempty"` + Active bool `json:"active,omitempty"` + AutoRenewal bool `json:"autoRenewal,omitempty"` + Upgradable bool `json:"upgradable,omitempty"` + Crossgradeable bool `json:"crossgradeable,omitempty"` + PurchasePastServerCutoffDate bool `json:"purchasePastServerCutoffDate,omitempty"` + SupportEntitlementNumber string `json:"supportEntitlementNumber,omitempty"` +} + func dataSourcePlugin() *schema.Resource { return &schema.Resource{ Read: dataSourcePluginRead, @@ -60,17 +83,115 @@ func dataSourcePlugin() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "vendor_name": { - Type: schema.TypeString, + "vendor": { + Type: schema.TypeMap, Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "link": { + Type: schema.TypeString, + Computed: true, + }, + "marketplace_link": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, }, - "vendor_link": { - Type: schema.TypeString, - Computed: true, - }, - "vendor_marketplace_link": { - Type: schema.TypeString, + "license": { + Type: schema.TypeList, Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "valid": { + Type: schema.TypeBool, + Computed: true, + }, + "evaluation": { + Type: schema.TypeBool, + Computed: true, + }, + "nearly_expired": { + Type: schema.TypeBool, + Computed: true, + }, + "maintenance_expiry_date": { + Type: schema.TypeString, + Computed: true, + }, + "maintenance_expired": { + Type: schema.TypeBool, + Computed: true, + }, + "license_type": { + Type: schema.TypeString, + Computed: true, + }, + "expiry_date": { + Type: schema.TypeString, + Computed: true, + }, + "raw_license": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + "renewable": { + Type: schema.TypeBool, + Computed: true, + }, + "organization_name": { + Type: schema.TypeString, + Computed: true, + }, + "contact_email": { + Type: schema.TypeString, + Computed: true, + }, + "enterprise": { + Type: schema.TypeBool, + Computed: true, + }, + "data_center": { + Type: schema.TypeBool, + Computed: true, + }, + "subscription": { + Type: schema.TypeBool, + Computed: true, + }, + "active": { + Type: schema.TypeBool, + Computed: true, + }, + "auto_renewal": { + Type: schema.TypeBool, + Computed: true, + }, + "upgradable": { + Type: schema.TypeBool, + Computed: true, + }, + "crossgradeable": { + Type: schema.TypeBool, + Computed: true, + }, + "purchase_past_server_cutoff_date": { + Type: schema.TypeBool, + Computed: true, + }, + "support_entitlement_number": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, }, }, } @@ -83,32 +204,76 @@ func dataSourcePluginRead(d *schema.ResourceData, m interface{}) error { return err } - if req.StatusCode == 200 { + var plugin Plugin - var plugin Plugin - - body, readErr := ioutil.ReadAll(req.Body) - if readErr != nil { - return readErr - } - - decodeErr := json.Unmarshal(body, &plugin) - if decodeErr != nil { - return decodeErr - } - - d.SetId(plugin.Key) - _ = d.Set("enabled", plugin.Enabled) - _ = d.Set("enabled_by_default", plugin.EnabledByDefault) - _ = d.Set("version", plugin.Version) - _ = d.Set("description", plugin.Description) - _ = d.Set("name", plugin.Name) - _ = d.Set("user_installed", plugin.UserInstalled) - _ = d.Set("optional", plugin.Optional) - _ = d.Set("vendor_name", plugin.Vendor.Name) - _ = d.Set("vendor_link", plugin.Vendor.Link) - _ = d.Set("vendor_marketplace_link", plugin.Vendor.MarketplaceLink) + body, readErr := ioutil.ReadAll(req.Body) + if readErr != nil { + return readErr } + decodeErr := json.Unmarshal(body, &plugin) + if decodeErr != nil { + return decodeErr + } + + d.SetId(plugin.Key) + _ = d.Set("enabled", plugin.Enabled) + _ = d.Set("enabled_by_default", plugin.EnabledByDefault) + _ = d.Set("version", plugin.Version) + _ = d.Set("description", plugin.Description) + _ = d.Set("name", plugin.Name) + _ = d.Set("user_installed", plugin.UserInstalled) + _ = d.Set("optional", plugin.Optional) + + vendor := map[string]string{ + "name": plugin.Vendor.Name, + "link": plugin.Vendor.Link, + "marketplace_link": plugin.Vendor.MarketplaceLink, + } + _ = d.Set("vendor", vendor) + + // Hit the license API to get license details + + req, err = client.Get(fmt.Sprintf("/rest/plugins/1.0/%s-key/license", d.Get("key").(string))) + if err != nil { + return err + } + + var pluginLicense PluginLicense + + body, readErr = ioutil.ReadAll(req.Body) + if readErr != nil { + return readErr + } + + decodeErr = json.Unmarshal(body, &pluginLicense) + if decodeErr != nil { + return decodeErr + } + + license := [1]map[string]interface{}{{ + "valid": pluginLicense.Valid, + "evaluation": pluginLicense.Evaluation, + "nearly_expired": pluginLicense.NearlyExpired, + "maintenance_expiry_date": pluginLicense.MaintenanceExpiryDate.String(), + "maintenance_expired": pluginLicense.MaintenanceExpired, + "license_type": pluginLicense.LicenseType, + "expiry_date": pluginLicense.ExpiryDate.String(), + "raw_license": pluginLicense.RawLicense, + "renewable": pluginLicense.Renewable, + "organization_name": pluginLicense.OrganizationName, + "contact_email": pluginLicense.ContactEmail, + "enterprise": pluginLicense.Enterprise, + "data_center": pluginLicense.DataCenter, + "subscription": pluginLicense.Subscription, + "active": pluginLicense.Active, + "auto_renewal": pluginLicense.AutoRenewal, + "upgradable": pluginLicense.Upgradable, + "crossgradeable": pluginLicense.Crossgradeable, + "purchase_past_server_cutoff_date": pluginLicense.PurchasePastServerCutoffDate, + "support_entitlement_number": pluginLicense.SupportEntitlementNumber, + }} + _ = d.Set("license", license) + return nil } diff --git a/bitbucket/data_plugin_test.go b/bitbucket/data_plugin_test.go index 7cb6afe..ecf5cb4 100644 --- a/bitbucket/data_plugin_test.go +++ b/bitbucket/data_plugin_test.go @@ -6,7 +6,56 @@ import ( "github.com/hashicorp/terraform/helper/resource" ) -func TestAccBitbucketDataPlugin(t *testing.T) { +func TestAccBitbucketDataPlugin_notifyer(t *testing.T) { + config := ` + data "bitbucketserver_plugin" "test" { + key = "nl.stefankohler.stash.stash-notification-plugin" + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "key", "nl.stefankohler.stash.stash-notification-plugin"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "enabled", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "enabled_by_default", "true"), + resource.TestCheckResourceAttrSet("data.bitbucketserver_plugin.test", "version"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "name", "Notifyr - Notification for Bitbucket"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "description", "Watch your repositories, branches, and tags and receive email notifications on changes."), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "user_installed", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "optional", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "vendor.name", "ASK Software"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "vendor.link", "http://www.stefankohler.nl/"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "vendor.marketplace_link", "http://www.stefankohler.nl/"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.valid", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.evaluation", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.nearly_expired", "true"), + resource.TestCheckResourceAttrSet("data.bitbucketserver_plugin.test", "license.0.maintenance_expiry_date"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.maintenance_expired", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.license_type", "DEVELOPER"), + resource.TestCheckResourceAttrSet("data.bitbucketserver_plugin.test", "license.0.expiry_date"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.raw_license", "AAABCA0ODAoPeNpdj01PwkAURffzKyZxZ1IyUzARkllQ24gRaQMtGnaP8VEmtjPNfFT59yJVFyzfubkn796Ux0Bz6SmbUM5nbDzj97RISxozHpMUnbSq88poUaLztFEStUN6MJZ2TaiVpu/YY2M6tI6sQrtHmx8qd74EZ+TBIvyUU/AoYs7jiE0jzknWQxMuifA2IBlUbnQ7AulVjwN9AaU9atASs69O2dNFU4wXJLc1aOUGw9w34JwCTTZoe7RPqUgep2X0Vm0n0fNut4gSxl/Jcnj9nFb6Q5tP/Ueu3L+0PHW4ghZFmm2zZV5k6/95CbR7Y9bYGo/zGrV3Ir4jRbDyCA6vt34DO8p3SDAsAhQnJjLD5k9Fr3uaIzkXKf83o5vDdQIUe4XequNCC3D+9ht9ZYhNZFKmnhc=X02dh"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.renewable", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.organization_name", "Atlassian"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.enterprise", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.data_center", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.subscription", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.active", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.auto_renewal", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.upgradable", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.crossgradeable", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.test", "license.0.purchase_past_server_cutoff_date", "true"), + ), + }, + }, + }) +} + +func TestAccBitbucketDataPlugin_upm(t *testing.T) { config := ` data "bitbucketserver_plugin" "upm" { key = "com.atlassian.upm.atlassian-universal-plugin-manager-plugin" @@ -28,9 +77,11 @@ func TestAccBitbucketDataPlugin(t *testing.T) { resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "description", "This is the plugin that provides the Atlassian Universal Plugin Manager."), resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "user_installed", "false"), resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "optional", "false"), - resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "vendor_name", "Atlassian"), - resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "vendor_link", "http://www.atlassian.com"), - resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "vendor_marketplace_link", "http://www.atlassian.com"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "vendor.name", "Atlassian"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "vendor.link", "http://www.atlassian.com"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "vendor.marketplace_link", "http://www.atlassian.com"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "license.0.valid", "false"), + resource.TestCheckResourceAttr("data.bitbucketserver_plugin.upm", "license.0.active", "false"), ), }, }, diff --git a/scripts/start-docker-compose.sh b/scripts/start-docker-compose.sh index 439c50c..e227bf2 100755 --- a/scripts/start-docker-compose.sh +++ b/scripts/start-docker-compose.sh @@ -11,7 +11,24 @@ if [ ! -f ${DIR}/docker-compose ]; then fi echo "--> Starting docker-compose" -${DIR}/docker-compose up -d +${DIR}/docker-compose up -d --build echo "--> Wait for bitbucket to be ready" bash ${DIR}/wait-for-url.sh --url http://localhost:7990/status --timeout 600 + +echo "--> Install a plugin for tests to reference licensing etc" +if [ ! -f ${DIR}/docker-compose-test-plugin.jar ]; then + curl -L -o ${DIR}/docker-compose-test-plugin.jar https://marketplace.atlassian.com/download/apps/1211185/version/400500101 +fi + +url="http://admin:admin@localhost:7990/rest/plugins/1.0/"; \ +token=$(curl -H 'X-Atlassian-Token: no-check' -sI "$url?os_authType=basic" | grep upm-token | cut -d: -f2- | tr -d '[[:space:]]'); \ +curl -H 'X-Atlassian-Token: no-check' -XPOST "$url?token=$token" -F plugin=@${DIR}/docker-compose-test-plugin.jar +sleep 10 + +echo "--> Apply a timebomb license for the plugin" +PLUGIN_LICENSE="AAABCA0ODAoPeNpdj01PwkAURffzKyZxZ1IyUzARkllQ24gRaQMtGnaP8VEmtjPNfFT59yJVFyzfubkn796Ux0Bz6SmbUM5nbDzj97RISxozHpMUnbSq88poUaLztFEStUN6MJZ2TaiVpu/YY2M6tI6sQrtHmx8qd74EZ+TBIvyUU/AoYs7jiE0jzknWQxMuifA2IBlUbnQ7AulVjwN9AaU9atASs69O2dNFU4wXJLc1aOUGw9w34JwCTTZoe7RPqUgep2X0Vm0n0fNut4gSxl/Jcnj9nFb6Q5tP/Ueu3L+0PHW4ghZFmm2zZV5k6/95CbR7Y9bYGo/zGrV3Ir4jRbDyCA6vt34DO8p3SDAsAhQnJjLD5k9Fr3uaIzkXKf83o5vDdQIUe4XequNCC3D+9ht9ZYhNZFKmnhc=X02dh" +PLUGIN_LICENSE_ENDPOINT="http://admin:admin@localhost:7990/rest/plugins/1.0/nl.stefankohler.stash.stash-notification-plugin-key/license?os_authType=basic" + +curl -H 'X-Atlassian-Token: no-check' -H 'Content-Type: application/vnd.atl.plugins+json' \ + -X PUT -d "{\"rawLicense\": \"${PLUGIN_LICENSE}\"}" ${PLUGIN_LICENSE_ENDPOINT}