From 9d0c85c37aed61ec19619b9757a9761d544aacd2 Mon Sep 17 00:00:00 2001 From: Gavin Bunney Date: Wed, 9 Oct 2019 11:22:26 -0700 Subject: [PATCH] Added `resource_admin_license` --- README.md | 32 ++++ bitbucket/json_types.go | 26 +++ bitbucket/provider.go | 1 + bitbucket/resource_admin_license.go | 158 +++++++++++++++++++ bitbucket/resource_admin_license_test.go | 53 +++++++ bitbucket/resource_admin_mail_server_test.go | 2 +- 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 bitbucket/json_types.go create mode 100644 bitbucket/resource_admin_license.go create mode 100644 bitbucket/resource_admin_license_test.go diff --git a/README.md b/README.md index 4c1701c..33690bc 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,38 @@ Additional to the above, the following attributes are emitted: $ terraform import bitbucketserver_repository.test TEST/test-01 ``` +### Set Server License + +```hcl +resource "bitbucketserver_admin_license" "main" { + license = "AAACLg0ODAoPeNqNVEtv4jAQvudXRNpbp" +} +``` + +* `license` - Required. License to apply. + +#### Attributes + +Additional to the above, the following attributes are emitted: + +* `clone_ssh` - URL for SSH cloning of the repository. +* `clone_https` - URL for HTTPS cloning of the repository. +* `creation_date` - License creation date. +* `purchase_date` - License purchase date. +* `expiry_date` - Expiry date of the license. +* `maintenance_expiry_date` - Expiry date of the maintenance period. +* `grace_period_end_date` - Grace period beyond expiry date. +* `maximum_users` - Maximum number of users for license. +* `unlimited_users` - Boolean flag if this is an unlimited user license. +* `server_id` - Server ID. +* `support_entitlement_number` - Entitlement number for support requests. + +#### Import License + +```bash +$ terraform import bitbucketserver_admin_license.main license +``` + ### Set Mail Server Configuration ```hcl diff --git a/bitbucket/json_types.go b/bitbucket/json_types.go new file mode 100644 index 0000000..c5da14c --- /dev/null +++ b/bitbucket/json_types.go @@ -0,0 +1,26 @@ +package bitbucket + +import ( + "strconv" + "strings" + "time" +) + +type jsonTime time.Time + +func (t jsonTime) MarshalJSON() ([]byte, error) { + return []byte(strconv.FormatInt(time.Time(t).Unix(), 10)), nil +} + +func (t *jsonTime) UnmarshalJSON(s []byte) (err error) { + r := strings.Replace(string(s), `"`, ``, -1) + + q, err := strconv.ParseInt(r, 10, 64) + if err != nil { + return err + } + *(*time.Time)(t) = time.Unix(q/1000, 0) + return +} + +func (t jsonTime) String() string { return time.Time(t).String() } diff --git a/bitbucket/provider.go b/bitbucket/provider.go index f7f219e..2ad62cb 100644 --- a/bitbucket/provider.go +++ b/bitbucket/provider.go @@ -29,6 +29,7 @@ func Provider() terraform.ResourceProvider { }, ConfigureFunc: providerConfigure, ResourcesMap: map[string]*schema.Resource{ + "bitbucketserver_admin_license": resourceAdminLicense(), "bitbucketserver_admin_mail_server": resourceAdminMailServer(), "bitbucketserver_project": resourceProject(), "bitbucketserver_repository": resourceRepository(), diff --git a/bitbucket/resource_admin_license.go b/bitbucket/resource_admin_license.go new file mode 100644 index 0000000..d5d553f --- /dev/null +++ b/bitbucket/resource_admin_license.go @@ -0,0 +1,158 @@ +package bitbucket + +import ( + "bytes" + "crypto/sha256" + "encoding/json" + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "io/ioutil" +) + +type License struct { + License string `json:"license,omitempty"` +} + +type LicenseResponse struct { + License string `json:"license,omitempty"` + CreationDate jsonTime `json:"creationDate,omitempty"` + PurchaseDate jsonTime `json:"purchaseDate,omitempty"` + ExpiryDate jsonTime `json:"expiryDate,omitempty"` + MaintenanceExpiryDate jsonTime `json:"maintenanceExpiryDate,omitempty"` + GracePeriodEndDate jsonTime `json:"gracePeriodEndDate,omitempty"` + MaximumNumberOfUsers int `json:"maximumNumberOfUsers,omitempty"` + UnlimitedUsers bool `json:"unlimitedNumberOfUsers,omitempty"` + ServerId string `json:"serverId,omitempty"` + SupportEntitlementNumber string `json:"supportEntitlementNumber,omitempty"` +} + +func resourceAdminLicense() *schema.Resource { + return &schema.Resource{ + Create: resourceAdminLicenseCreate, + Update: resourceAdminLicenseUpdate, + Read: resourceAdminLicenseRead, + Delete: resourceAdminLicenseDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "license": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "creation_date": { + Type: schema.TypeString, + Computed: true, + }, + "purchase_date": { + Type: schema.TypeString, + Computed: true, + }, + "expiry_date": { + Type: schema.TypeString, + Computed: true, + }, + "maintenance_expiry_date": { + Type: schema.TypeString, + Computed: true, + }, + "grace_period_end_date": { + Type: schema.TypeString, + Computed: true, + }, + "maximum_users": { + Type: schema.TypeInt, + Computed: true, + }, + "unlimited_users": { + Type: schema.TypeBool, + Computed: true, + }, + "server_id": { + Type: schema.TypeString, + Computed: true, + }, + "support_entitlement_number": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func newLicenseFromResource(d *schema.ResourceData) *License { + license := &License{ + License: d.Get("license").(string), + } + + return license +} + +func resourceAdminLicenseUpdate(d *schema.ResourceData, m interface{}) error { + client := m.(*BitbucketClient) + license := newLicenseFromResource(d) + + bytedata, err := json.Marshal(license) + + if err != nil { + return err + } + + _, err = client.Post("/rest/api/1.0/admin/license", bytes.NewBuffer(bytedata)) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("%x", sha256.Sum256([]byte(license.License)))) + return resourceAdminLicenseRead(d, m) +} + +func resourceAdminLicenseCreate(d *schema.ResourceData, m interface{}) error { + return resourceAdminLicenseUpdate(d, m) +} + +func resourceAdminLicenseRead(d *schema.ResourceData, m interface{}) error { + + client := m.(*BitbucketClient) + req, err := client.Get("/rest/api/1.0/admin/license") + + if err != nil { + return err + } + + if req.StatusCode == 200 { + + var license LicenseResponse + + body, readerr := ioutil.ReadAll(req.Body) + if readerr != nil { + return readerr + } + + decodeerr := json.Unmarshal(body, &license) + if decodeerr != nil { + return decodeerr + } + + d.Set("license", license.License) + d.Set("creation_date", license.CreationDate.String()) + d.Set("purchase_date", license.PurchaseDate.String()) + d.Set("expiry_date", license.ExpiryDate.String()) + d.Set("maintenance_expiry_date", license.MaintenanceExpiryDate.String()) + d.Set("grace_period_end_date", license.GracePeriodEndDate.String()) + d.Set("maximum_users", license.MaximumNumberOfUsers) + d.Set("unlimited_users", license.UnlimitedUsers) + d.Set("server_id", license.ServerId) + d.Set("support_entitlement_number", license.SupportEntitlementNumber) + } + + return nil +} + +func resourceAdminLicenseDelete(d *schema.ResourceData, m interface{}) error { + client := m.(*BitbucketClient) + _, err := client.Delete("/rest/api/1.0/admin/mail-server") + return err +} diff --git a/bitbucket/resource_admin_license_test.go b/bitbucket/resource_admin_license_test.go new file mode 100644 index 0000000..3437f24 --- /dev/null +++ b/bitbucket/resource_admin_license_test.go @@ -0,0 +1,53 @@ +package bitbucket + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccBitbucketAdminLicense(t *testing.T) { + testAccBitbucketAdminLicenseConfig := ` + resource "bitbucketserver_admin_license" "test" { + license = "AAACLg0ODAoPeNqNVEtv4jAQvudXRNpbpUSEx6FIOQBxW3ZZiCB0V1WllXEG8DbYke3A8u/XdUgVQyg9ZvLN+HuM/e1BUHdGlNvuuEHQ73X73Y4bR4nbbgU9ZwFiD2IchcPH+8T7vXzuej9eXp68YSv45UwoASYhOeYwxTsIE7RIxtNHhwh+SP3a33D0XnntuxHsIeM5CIdwtvYxUXQPoRIF6KaC0FUGVlEB3v0hOAOWYiH9abFbgZith3i34nwOO65gsAGmZBhUbNC/nIpjhBWEcefJWelzqIDPWz/OtjmXRYv2XyqwnwueFkT57x8e4cLmbCD1QnX0UoKQoRc4EUgiaK4oZ2ECUrlZeay75sLNs2JDmZtWR8oPCfWZGwHAtjzXgIo0SqmZiKYJmsfz8QI5aI+zApuq6fqJKVPAMCPnNpk4LPW6kBWgkZb+kQAzzzS2g6Dnte69Tqvsr4SOskIqEFOeggz1v4zrHbr0yLJR8rU64FpQpVtBy1mZxM4CnHC9Faf8tKMnTF1AiXORFixyQaWto3RZ+ncWLXtMg6EnKZZRpmQNb2R8tnJXFulCfXmXLry7TrHBWn2HNVyH8WYxj9AzmsxiNL/R88Xg6rA1lVs4QpO5titxhplJcCY2mFFZLutAZVhKipm15/VhJx36YVqyN8YP7IaGC1+lwnJ7Q5pJpNmxk5hP3qovutY8Pi4E2WIJ59esnr1p+T6eD67teBVCHf+ga+ho4/4D9YItZDAsAhQ5qQ6pASJ+SA7YG9zthbLxRoBBEwIURQr5Zy1B8PonepyLz3UhL7kMVEs=X02q6" + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckBitbucketAdminLicenseDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBitbucketAdminLicenseConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckBitbucketAdminLicenseExists("bitbucketserver_admin_license.test"), + ), + }, + }, + }) +} + +func testAccCheckBitbucketAdminLicenseDestroy(s *terraform.State) error { + _, ok := s.RootModule().Resources["bitbucketserver_admin_license.test"] + if !ok { + return fmt.Errorf("not found %s", "bitbucketserver_admin_license.test") + } + + return nil +} + +func testAccCheckBitbucketAdminLicenseExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("not found %s", n) + } + if rs.Primary.ID == "" { + return fmt.Errorf("no license ID is set") + } + return nil + } +} diff --git a/bitbucket/resource_admin_mail_server_test.go b/bitbucket/resource_admin_mail_server_test.go index 75cc8d0..ad38fe0 100644 --- a/bitbucket/resource_admin_mail_server_test.go +++ b/bitbucket/resource_admin_mail_server_test.go @@ -57,7 +57,7 @@ func testAccCheckBitbucketAdminMailServerExists(n string) resource.TestCheckFunc return fmt.Errorf("not found %s", n) } if rs.Primary.ID == "" { - return fmt.Errorf("no project ID is set") + return fmt.Errorf("no mail ID is set") } return nil }