Skip to content

Commit

Permalink
Merge pull request #21 from OctopusDeploy/certs
Browse files Browse the repository at this point in the history
Add support for certificates
  • Loading branch information
jeff-french authored Jul 13, 2019
2 parents dbe5dee + afe0194 commit f586a4b
Show file tree
Hide file tree
Showing 10 changed files with 507 additions and 12 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module github.com/OctopusDeploy/terraform-provider-octopusdeploy

require (
github.com/OctopusDeploy/go-octopusdeploy v1.1.0
github.com/OctopusDeploy/go-octopusdeploy v1.3.0
github.com/apparentlymart/go-cidr v1.0.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/aws/aws-sdk-go v1.15.53 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ github.com/OctopusDeploy/go-octopusdeploy v1.0.0 h1:JweXaa6zTIv8NOpLDLomzceVGV+v
github.com/OctopusDeploy/go-octopusdeploy v1.0.0/go.mod h1:WyBvcyhFPMULbZwFFWOmt6/irqrfZ/WqCy7ufa8/CGE=
github.com/OctopusDeploy/go-octopusdeploy v1.1.0 h1:zVnapVTe8MDhiqEszKLlZuXVrf7fvy96d8IwgWQwPOE=
github.com/OctopusDeploy/go-octopusdeploy v1.1.0/go.mod h1:WyBvcyhFPMULbZwFFWOmt6/irqrfZ/WqCy7ufa8/CGE=
github.com/OctopusDeploy/go-octopusdeploy v1.2.0 h1:EeWEaiHuEAOxNGEHskNpmGiAXf9hZYH/E1sksGO962A=
github.com/OctopusDeploy/go-octopusdeploy v1.2.0/go.mod h1:WyBvcyhFPMULbZwFFWOmt6/irqrfZ/WqCy7ufa8/CGE=
github.com/OctopusDeploy/go-octopusdeploy v1.2.1 h1:wfyln0AKOg74dBJM6V2hKHxskXQzMxdfd4sIjX5GT4s=
github.com/OctopusDeploy/go-octopusdeploy v1.2.1/go.mod h1:WyBvcyhFPMULbZwFFWOmt6/irqrfZ/WqCy7ufa8/CGE=
github.com/OctopusDeploy/go-octopusdeploy v1.3.0 h1:ZekYly62VzsHx7PHSSPI8bOKMNNz1DhlonIeWdPobO8=
github.com/OctopusDeploy/go-octopusdeploy v1.3.0/go.mod h1:WyBvcyhFPMULbZwFFWOmt6/irqrfZ/WqCy7ufa8/CGE=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-cidr v1.0.0 h1:lGDvXx8Lv9QHjrAVP7jyzleG4F9+FkRhJcEsDFxeb8w=
Expand Down
1 change: 1 addition & 0 deletions octopusdeploy/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func Provider() terraform.ResourceProvider {
"octopusdeploy_lifecycle": resourceLifecycle(),
"octopusdeploy_deployment_process": resourceDeploymentProcess(),
"octopusdeploy_tag_set": resourceTagSet(),
"octopusdeploy_certificate": resourceCertificate(),
},
Schema: map[string]*schema.Schema{
"address": {
Expand Down
199 changes: 199 additions & 0 deletions octopusdeploy/resource_certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package octopusdeploy

import (
"fmt"

"github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceCertificate() *schema.Resource {
return &schema.Resource{
Create: resourceCertificateCreate,
Read: resourceCertificateRead,
Update: resourceCertificateUpdate,
Delete: resourceCertificateDelete,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"notes": {
Type: schema.TypeString,
Optional: true,
},
"certificate_data": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
},
"password": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
"environment_ids": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"tenanted_deployment_participation": getTenantedDeploymentSchema(),
"tenant_ids": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"tenant_tags": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func resourceCertificateRead(d *schema.ResourceData, m interface{}) error {
client := m.(*octopusdeploy.Client)

certificateId := d.Id()
certificate, err := client.Certificate.Get(certificateId)

if err == octopusdeploy.ErrItemNotFound {
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading certificate %s: %s", certificateId, err.Error())
}

d.Set("name", certificate.Name)
d.Set("notes", certificate.Notes)
d.Set("environment_ids", certificate.EnvironmentIds)
d.Set("tenanted_deployment_participation", certificate.TenantedDeploymentParticipation)
d.Set("tenant_ids", certificate.TenantIds)
d.Set("tenant_tags", certificate.TenantTags)

return nil
}

func buildCertificateResource(d *schema.ResourceData) *octopusdeploy.Certificate {
certificateName := d.Get("name").(string)

var notes string
var certificateData string
var password string
var environmentIds []string
var tenantedDeploymentParticipation string
var tenantIds []string
var tenantTags []string

notesInterface, ok := d.GetOk("notes")
if ok {
notes = notesInterface.(string)
}

certificateDataInterface, ok := d.GetOk("certificate_data")
if ok {
certificateData = certificateDataInterface.(string)
}

passwordInterface, ok := d.GetOk("password")
if ok {
password = passwordInterface.(string)
}

environmentIdsInterface, ok := d.GetOk("environment_ids")
if ok {
environmentIds = getSliceFromTerraformTypeList(environmentIdsInterface)
}

if environmentIds == nil {
environmentIds = []string{}
}

tenantedDeploymentParticipationInterface, ok := d.GetOk("tenanted_deployment_participation")
if ok {
tenantedDeploymentParticipation = tenantedDeploymentParticipationInterface.(string)
}

tenantIdsInterface, ok := d.GetOk("tenant_ids")
if ok {
tenantIds = getSliceFromTerraformTypeList(tenantIdsInterface)
}

if tenantIds == nil {
tenantIds = []string{}
}

tenantTagsInterface, ok := d.GetOk("tenant_tags")
if ok {
tenantTags = getSliceFromTerraformTypeList(tenantTagsInterface)
}

if tenantTags == nil {
tenantTags = []string{}
}

var certificate = octopusdeploy.NewCertificate(certificateName, octopusdeploy.SensitiveValue{NewValue: certificateData}, octopusdeploy.SensitiveValue{NewValue: password})
certificate.Notes = notes
certificate.EnvironmentIds = environmentIds
certificate.TenantedDeploymentParticipation = tenantedDeploymentParticipation
certificate.TenantIds = tenantIds
certificate.TenantTags = tenantTags

return certificate
}

func resourceCertificateCreate(d *schema.ResourceData, m interface{}) error {
client := m.(*octopusdeploy.Client)

newCertificate := buildCertificateResource(d)
certificate, err := client.Certificate.Add(newCertificate)

if err != nil {
return fmt.Errorf("error creating certificate %s: %s", newCertificate.Name, err.Error())
}

d.SetId(certificate.ID)

return nil
}

func resourceCertificateUpdate(d *schema.ResourceData, m interface{}) error {
certificate := buildCertificateResource(d)
certificate.ID = d.Id()

client := m.(*octopusdeploy.Client)

updatedCertificate, err := client.Certificate.Replace(certificate)

if err != nil {
return fmt.Errorf("error updating certificate id %s: %s", d.Id(), err.Error())
}

d.SetId(updatedCertificate.ID)
return nil
}

func resourceCertificateDelete(d *schema.ResourceData, m interface{}) error {
client := m.(*octopusdeploy.Client)

certificateId := d.Id()

err := client.Certificate.Delete(certificateId)

if err != nil {
return fmt.Errorf("error deleting certificate id %s: %s", certificateId, err.Error())
}

d.SetId("")
return nil
}
111 changes: 111 additions & 0 deletions octopusdeploy/resource_certificate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package octopusdeploy

import (
"fmt"
"testing"

"github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccOctopusDeployCertificateBasic(t *testing.T) {
const certPrefix = "octopusdeploy_certificate.foo"
const certName = "Testing one two three"
const certNotes = "Cert notes blah blah blah"
const certData = "MIIDiDCCAnACCQDXHofnqz05ITANBgkqhkiG9w0BAQsFADCBhTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE9rbGFob21hMQ8wDQYDVQQHDAZOb3JtYW4xEzARBgNVBAoMCk1vb25zd2l0Y2gxGTAXBgNVBAMMEGRlbW8ub2N0b3B1cy5jb20xIjAgBgkqhkiG9w0BCQEWE2plZmZAbW9vbnN3aXRjaC5jb20wHhcNMTkwNjE0MjExMzI1WhcNMjAwNjEzMjExMzI1WjCBhTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE9rbGFob21hMQ8wDQYDVQQHDAZOb3JtYW4xEzARBgNVBAoMCk1vb25zd2l0Y2gxGTAXBgNVBAMMEGRlbW8ub2N0b3B1cy5jb20xIjAgBgkqhkiG9w0BCQEWE2plZmZAbW9vbnN3aXRjaC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSTiD0OHyFDMH9O+d/h3AiqcuvpvUgRkKjf+whZ6mVlQnGkvPddRTUY48xCEaQ4QD1MAVJcGaJ2PU4NxwhrQgHqWW8TQkAZESL4wfzSwIKO2NX/I2tWqyv7a0uA/WdtlWQye+2oPV5rCnS0kM75X+gjEwOTpFh/ryS6KhMPFDb0zeNGREdg6564FdxWSvN4ppUZMqhvMpfzM7rsDWqEzYsMaQ4CNJDFdWkG89D4j5qk4b4Qb4m+l7QINdmYIXf4qO/0LE1WcfIkCpAS65tjc/hefIHmYtj/E/ijoNJbWKZDK3WLZg3zq99Ipqv/9DFvSiMQFBhZT0jO2B5d5zBUuIHAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAKsa4gaW7GhByu8aq56h99DaIl1LauI5WMVH8Q9Qpapho2VLRIpfwGeI5eENFoXwuKrnJp1ncsCqGnMQnugQHS+SrruS3Yyl0Uog4Zak9GbbK6qn+olx7GNJbsckmD371lqQOaKITLqYzK6kTc7/v8Cv0BwHFCBda1OCrmeVBSaarucPxZhGxzLAielzHHdlkZFQT/oO2VR3thhURIqtni7jVQ2MoeZF1ccvmAfVbzr/QnlNe/jrcmyPYymuF2JyrezzIjlKuiDhalKqwqkCHpOOgzV4y6BFuS+0w3DS8pa07nUudZ6E0kZzvhjjiyAx/sBdX6ZDdUjP9TDJMM4f5YA="
const tagSetName = "TagSet"
const tagName = "Tag"
const envName = "Test Env"
var tenantTags = fmt.Sprintf("%s/%s", tagSetName, tagName)
const tenantedDeploymentParticipation = "TenantedOrUntenanted"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testOctopusDeployCertificateDestroy,
Steps: []resource.TestStep{
{
Config: testCertificateBasic(tagSetName, tagName, envName, certName, certNotes, certData, tenantedDeploymentParticipation),
Check: resource.ComposeTestCheckFunc(
testOctopusDeployCertificateExists(certPrefix),
resource.TestCheckResourceAttr(
certPrefix, "name", certName),
resource.TestCheckResourceAttr(
certPrefix, "notes", certNotes),
resource.TestCheckResourceAttr(
certPrefix, "certificate_data", certData),
resource.TestCheckResourceAttr(
certPrefix, "tenant_tags.0", tenantTags),
resource.TestCheckResourceAttr(
certPrefix, "tenanted_deployment_participation", tenantedDeploymentParticipation),
),
},
},
})
}

func testCertificateBasic(tagSetName string, tagName string, environmentName string, certName string, notes string, certificateData string, tenantedDeploymentParticipation string) string {
return fmt.Sprintf(`
resource "octopusdeploy_tag_set" "testtagset" {
name = "%s"
tag {
name = "%s"
color = "#6e6e6f"
}
}
resource "octopusdeploy_environment" "test_env" {
name = "%s"
}
resource "octopusdeploy_certificate" "foo" {
name = "%s"
notes = "%s"
certificate_data = "%s"
environment_ids = ["${octopusdeploy_environment.test_env.id}"]
tenanted_deployment_participation = "%s"
tenant_tags = ["${octopusdeploy_tag_set.testtagset.name}/%s"]
}
`,
tagSetName, tagName, environmentName, certName, notes, certificateData, tenantedDeploymentParticipation, tagName,
)
}

func testOctopusDeployCertificateExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testAccProvider.Meta().(*octopusdeploy.Client)
return existscertHelper(s, client)
}
}

func existscertHelper(s *terraform.State, client *octopusdeploy.Client) error {

certId := s.RootModule().Resources["octopusdeploy_certificate.foo"].Primary.ID

if _, err := client.Certificate.Get(certId); err != nil {
return fmt.Errorf("Received an error retrieving certificate %s", err)
}

return nil
}

func testOctopusDeployCertificateDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*octopusdeploy.Client)
return destroycertHelper(s, client)
}

func destroycertHelper(s *terraform.State, client *octopusdeploy.Client) error {

certId := s.RootModule().Resources["octopusdeploy_certificate.foo"].Primary.ID

if _, err := client.Certificate.Get(certId); err != nil {
if err == octopusdeploy.ErrItemNotFound {
return nil
}
return fmt.Errorf("Received an error retrieving certificate %s", err)
}
return fmt.Errorf("Certificate still exists")
}
11 changes: 1 addition & 10 deletions octopusdeploy/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,7 @@ func resourceProject() *schema.Resource {
Optional: true,
Default: false,
},
"tenanted_deployment_mode": {
Type: schema.TypeString,
Optional: true,
Default: "Untenanted",
ValidateFunc: validateValueFunc([]string{
"Untenanted",
"TenantedOrUntenanted",
"Tenanted",
}),
},
"tenanted_deployment_mode": getTenantedDeploymentSchema(),
"included_library_variable_sets": {
Type: schema.TypeList,
Optional: true,
Expand Down
13 changes: 13 additions & 0 deletions octopusdeploy/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,16 @@ func getStringOrEmpty(tfAttr interface{}) string {
return tfAttr.(string)

}

func getTenantedDeploymentSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "Untenanted",
ValidateFunc: validateValueFunc([]string{
"Untenanted",
"TenantedOrUntenanted",
"Tenanted",
}),
}
}
Loading

0 comments on commit f586a4b

Please sign in to comment.