diff --git a/go.mod b/go.mod index 6691a3093..0e35bc5e4 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/OctopusDeploy/terraform-provider-octopusdeploy require ( - github.com/OctopusDeploy/go-octopusdeploy v1.3.0 + github.com/OctopusDeploy/go-octopusdeploy v1.4.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 diff --git a/go.sum b/go.sum index 7e678aa1f..2adb38233 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/OctopusDeploy/go-octopusdeploy v1.2.1 h1:wfyln0AKOg74dBJM6V2hKHxskXQz 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/OctopusDeploy/go-octopusdeploy v1.4.0 h1:uTBRPoGcS3tN40LKQb70xq+m/hpKX1fExfLhGAAxHDk= +github.com/OctopusDeploy/go-octopusdeploy v1.4.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= diff --git a/octopusdeploy/data_machine.go b/octopusdeploy/data_machine.go index a7ea43598..b3f19ffba 100644 --- a/octopusdeploy/data_machine.go +++ b/octopusdeploy/data_machine.go @@ -117,7 +117,7 @@ func dataMachineReadByName(d *schema.ResourceData, m interface{}) error { client := m.(*octopusdeploy.Client) machineName := d.Get("name").(string) - machines, err := client.Machine.GetAll() + machine, err := client.Machine.GetByName(machineName) if err == octopusdeploy.ErrItemNotFound { return nil } @@ -125,34 +125,29 @@ func dataMachineReadByName(d *schema.ResourceData, m interface{}) error { return fmt.Errorf("error reading machine with name %s: %s", machineName, err.Error()) } - for _, m := range *machines { - if m.Name == machineName { - d.SetId(m.ID) - d.Set("endpoint_communicationstyle", m.Endpoint.CommunicationStyle) - d.Set("endpoint_id", m.Endpoint.ID) - d.Set("endpoint_proxyid", m.Endpoint.ProxyID) - d.Set("endpoint_tentacleversiondetails_upgradelocked", m.Endpoint.TentacleVersionDetails.UpgradeLocked) - d.Set("endpoint_tentacleversiondetails_upgraderequired", m.Endpoint.TentacleVersionDetails.UpgradeRequired) - d.Set("endpoint_tentacleversiondetails_upgradesuggested", m.Endpoint.TentacleVersionDetails.UpgradeSuggested) - d.Set("endpoint_tentacleversiondetails_version", m.Endpoint.TentacleVersionDetails.Version) - d.Set("endpoint_thumbprint", m.Endpoint.Thumbprint) - d.Set("endpoint_uri", m.Endpoint.URI) - d.Set("environments", m.EnvironmentIDs) - d.Set("haslatestcalamari", m.HasLatestCalamari) - d.Set("isdisabled", m.IsDisabled) - d.Set("isinprocess", m.IsInProcess) - d.Set("machinepolicy", m.MachinePolicyID) - d.Set("roles", m.Roles) - d.Set("status", m.Status) - d.Set("statussummary", m.StatusSummary) - d.Set("tenanteddeploymentparticipation", m.TenantedDeploymentParticipation) - d.Set("tenantids", m.TenantIDs) - d.Set("tenanttags", m.TenantTags) - //d.Set("thumbprint", m.Thumbprint) - //d.Set("uri", m.URI) - - } - } + d.SetId(machine.ID) + d.Set("endpoint_communicationstyle", machine.Endpoint.CommunicationStyle) + d.Set("endpoint_id", machine.Endpoint.ID) + d.Set("endpoint_proxyid", machine.Endpoint.ProxyID) + d.Set("endpoint_tentacleversiondetails_upgradelocked", machine.Endpoint.TentacleVersionDetails.UpgradeLocked) + d.Set("endpoint_tentacleversiondetails_upgraderequired", machine.Endpoint.TentacleVersionDetails.UpgradeRequired) + d.Set("endpoint_tentacleversiondetails_upgradesuggested", machine.Endpoint.TentacleVersionDetails.UpgradeSuggested) + d.Set("endpoint_tentacleversiondetails_version", machine.Endpoint.TentacleVersionDetails.Version) + d.Set("endpoint_thumbprint", machine.Endpoint.Thumbprint) + d.Set("endpoint_uri", machine.Endpoint.URI) + d.Set("environments", machine.EnvironmentIDs) + d.Set("haslatestcalamari", machine.HasLatestCalamari) + d.Set("isdisabled", machine.IsDisabled) + d.Set("isinprocess", machine.IsInProcess) + d.Set("machinepolicy", machine.MachinePolicyID) + d.Set("roles", machine.Roles) + d.Set("status", machine.Status) + d.Set("statussummary", machine.StatusSummary) + d.Set("tenanteddeploymentparticipation", machine.TenantedDeploymentParticipation) + d.Set("tenantids", machine.TenantIDs) + d.Set("tenanttags", machine.TenantTags) + //d.Set("thumbprint", machine.Thumbprint) + //d.Set("uri", machine.URI) return nil } diff --git a/octopusdeploy/resource_account.go b/octopusdeploy/resource_account.go index 7e788c806..cbd893a6c 100644 --- a/octopusdeploy/resource_account.go +++ b/octopusdeploy/resource_account.go @@ -19,25 +19,32 @@ func resourceAccount() *schema.Resource { Type: schema.TypeString, Required: true, }, + "environments": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, "account_type": { Type: schema.TypeString, Required: true, }, "client_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "tenant_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "subscription_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "client_secret": { Type: schema.TypeString, - Required: true, + Optional: true, }, "tenant_tags": { Type: schema.TypeList, @@ -48,13 +55,17 @@ func resourceAccount() *schema.Resource { }, "tenanted_deployment_participation": { Type: schema.TypeString, - Required: true, + Optional: true, ValidateFunc: validateValueFunc([]string{ "Untenanted", "TenantedOrUntenanted", "Tenanted", }), }, + "token": { + Type: schema.TypeString, + Optional: true, + }, }, } } @@ -75,6 +86,7 @@ func resourceAccountRead(d *schema.ResourceData, m interface{}) error { } d.Set("name", account.Name) + d.Set("environments", account.EnvironmentIDs) d.Set("account_type", account.AccountType) d.Set("client_id", account.ClientId) d.Set("tenant_id", account.TenantId) @@ -82,6 +94,7 @@ func resourceAccountRead(d *schema.ResourceData, m interface{}) error { d.Set("client_secret", account.Password) d.Set("tenant_tags", account.TenantTags) d.Set("tenanted_deployment_participation", account.TenantedDeploymentParticipation) + d.Set("token", account.Token) return nil } @@ -89,6 +102,7 @@ func resourceAccountRead(d *schema.ResourceData, m interface{}) error { func buildAccountResource(d *schema.ResourceData) *octopusdeploy.Account { accountName := d.Get("name").(string) + var environments []string var accountType string var clientId string var tenantId string @@ -96,6 +110,12 @@ func buildAccountResource(d *schema.ResourceData) *octopusdeploy.Account { var clientSecret string var tenantTags []string var tenantedDeploymentParticipation string + var token string + + environmentsInterface, ok := d.GetOk("environments") + if ok { + environments = getSliceFromTerraformTypeList(environmentsInterface) + } accountTypeInterface, ok := d.GetOk("account_type") if ok { @@ -136,7 +156,13 @@ func buildAccountResource(d *schema.ResourceData) *octopusdeploy.Account { tenantTags = []string{} } + tokenInterface, ok := d.GetOk("token") + if ok { + token = tokenInterface.(string) + } + var account = octopusdeploy.NewAccount(accountName, accountType) + account.EnvironmentIDs = environments account.ClientId = clientId account.TenantId = tenantId account.Password = octopusdeploy.SensitiveValue{ @@ -145,6 +171,9 @@ func buildAccountResource(d *schema.ResourceData) *octopusdeploy.Account { account.SubscriptionNumber = subscriptionId account.TenantTags = tenantTags account.TenantedDeploymentParticipation = tenantedDeploymentParticipation + account.Token = octopusdeploy.SensitiveValue{ + NewValue: token, + } return account } diff --git a/octopusdeploy/resource_machine.go b/octopusdeploy/resource_machine.go index 00d155923..a130f0b07 100644 --- a/octopusdeploy/resource_machine.go +++ b/octopusdeploy/resource_machine.go @@ -2,6 +2,7 @@ package octopusdeploy import ( "fmt" + "strconv" "github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy" "github.com/hashicorp/terraform/helper/schema" @@ -41,6 +42,7 @@ func resourceMachine() *schema.Resource { "AzureWebApp", "Ftp", "AzureCloudService", + "Kubernetes" }), }, @@ -56,6 +58,52 @@ func resourceMachine() *schema.Resource { Type: schema.TypeString, Required: true, }, + "clustercertificate": { + Type: schema.TypeString, + Optional: true, + }, + "clusterurl": { + Type: schema.TypeString, + Optional: true, + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + }, + "skiptlsverification": { + Type: schema.TypeBool, + Optional: true, + }, + "defaultworkerpoolid": { + Type: schema.TypeString, + Optional: true, + }, + "authentication": { + Type: schema.TypeSet, + MaxItems: 1, + MinItems: 0, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "accountid": { + Type: schema.TypeString, + Optional: true, + }, + "clientcertificate": { + Type: schema.TypeString, + Optional: true, + }, + "authenticationtype": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "KubernetesCertificate", + "KubernetesStandard", + }), + }, + }, + }, + }, }, }, }, @@ -209,10 +257,29 @@ func buildMachineResource(d *schema.ResourceData) *octopusdeploy.Machine { } tfMachine.Endpoint = &octopusdeploy.MachineEndpoint{ - URI: tfSchemaList["uri"].(string), - Thumbprint: tfSchemaList["thumbprint"].(string), - CommunicationStyle: tfSchemaList["communicationstyle"].(string), - ProxyID: proxyid, + URI: tfSchemaList["uri"].(string), + Thumbprint: tfSchemaList["thumbprint"].(string), + CommunicationStyle: tfSchemaList["communicationstyle"].(string), + ProxyID: proxyid, + ClusterCertificate: tfSchemaList["clustercertificate"].(string), + ClusterURL: tfSchemaList["clusterurl"].(string), + SkipTLSVerification: strconv.FormatBool(tfSchemaList["skiptlsverification"].(bool)), + DefaultWorkerPoolID: tfSchemaList["defaultworkerpoolid"].(string), + } + + tfAuthenticationSchemaSetInterface, ok := tfSchemaList["authentication"] + if ok { + tfAuthenticationSchemaSet := tfAuthenticationSchemaSetInterface.(*schema.Set) + if len(tfAuthenticationSchemaSet.List()) == 1 { + //Get the first element in the list, which is a map of the interfaces + tfAuthenticationSchemaList := tfAuthenticationSchemaSet.List()[0].(map[string]interface{}) + + tfMachine.Endpoint.Authentication = &octopusdeploy.MachineEndpointAuthentication{ + AccountID: tfAuthenticationSchemaList["accountid"].(string), + ClientCertificate: tfAuthenticationSchemaList["clientcertificate"].(string), + AuthenticationType: tfAuthenticationSchemaList["authenticationtype"].(string), + } + } } return tfMachine diff --git a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/account.go b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/account.go index bc8cbd743..72a358fe3 100644 --- a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/account.go +++ b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/account.go @@ -24,6 +24,7 @@ type Accounts struct { type Account struct { ID string `json:"Id"` + EnvironmentIDs []string `json:"EnvironmentIds"` Name string `json:"Name"` AccountType string `json:"AccountType"` SubscriptionNumber string `json:"SubscriptionNumber"` @@ -32,6 +33,7 @@ type Account struct { Password SensitiveValue `json:"Password"` TenantTags []string `json:"TenantTags,omitempty"` TenantedDeploymentParticipation string `json:"TenantedDeploymentParticipation"` + Token SensitiveValue `json:"Token,omitempty"` } func (t *Account) Validate() error { diff --git a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/channels.go b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/channels.go new file mode 100644 index 000000000..2a512ffca --- /dev/null +++ b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/channels.go @@ -0,0 +1,160 @@ +package octopusdeploy + +import ( + "fmt" + + "github.com/dghubble/sling" + "gopkg.in/go-playground/validator.v9" +) + +type ChannelService struct { + sling *sling.Sling +} + +func NewChannelService(sling *sling.Sling) *ChannelService { + return &ChannelService{ + sling: sling, + } +} + +type Channels struct { + Items []Channel `json:"Items"` + PagedResults +} + +type Channel struct { + Description string `json:"Description"` + ID string `json:"Id,omitempty"` + IsDefault bool `json:"IsDefault"` + LifecycleID string `json:"LifecycleId"` + Name string `json:"Name"` + ProjectID string `json:"ProjectId"` + Rules []ChannelRule `json:"Rules,omitempty"` + TenantTags []string `json:"TenantedDeploymentMode,omitempty"` +} + +type ChannelRule struct { + // name of Package step(s) this rule applies to + Actions []string `json:"Actions,omitempty"` + + // Id + ID string `json:"Id,omitempty"` + + // Pre-release tag + Tag string `json:"Tag,omitempty"` + + //Use the NuGet or Maven versioning syntax (depending on the feed type) + //to specify the range of versions to include + VersionRange string `json:"VersionRange,omitempty"` +} + +func (d *Channels) Validate() error { + validate := validator.New() + + err := validate.Struct(d) + + if err != nil { + return err + } + + return nil +} + +func (s *ChannelService) Get(channelID string) (*Channel, error) { + path := fmt.Sprintf("channels/%s", channelID) + resp, err := apiGet(s.sling, new(Channel), path) + + if err != nil { + return nil, err + } + + return resp.(*Channel), nil +} + +func (s *ChannelService) GetAll() (*[]Channel, error) { + var ch []Channel + + path := "channel" + + loadNextPage := true + + for loadNextPage { + resp, err := apiGet(s.sling, new(Channels), path) + + if err != nil { + return nil, err + } + + r := resp.(*Channels) + + for _, item := range r.Items { + ch = append(ch, item) + } + + path, loadNextPage = LoadNextPage(r.PagedResults) + } + + return &ch, nil +} + +// Add adds a new channel +func (s *ChannelService) Add(channel *Channel) (*Channel, error) { + err := ValidateChannelValues(channel) + if err != nil { + return nil, err + } + + resp, err := apiAdd(s.sling, channel, new(Channel), "channels") + + if err != nil { + return nil, err + } + + return resp.(*Channel), nil +} + +// ValidateChannelValues checks the values of a Channel object to see if they are suitable for +// sending to Octopus Deploy. Used when adding or updating channels. +func ValidateChannelValues(Channel *Channel) error { + return ValidateMultipleProperties([]error{ + ValidateRequiredPropertyValue("Name", Channel.Name), + ValidateRequiredPropertyValue("ProjectID", Channel.ProjectID), + }) +} + +func NewChannel(name, description, projectID string) *Channel { + return &Channel{ + Name: name, + ProjectID: projectID, + Description: description, + } +} + +// Delete deletes an existing channel in Octopus Deploy +func (s *ChannelService) Delete(channelid string) error { + path := fmt.Sprintf("channels/%s", channelid) + err := apiDelete(s.sling, path) + + if err != nil { + return err + } + + return nil +} + +// Update updates an existing channel in Octopus Deploy +func (s *ChannelService) Update(channel *Channel) (*Channel, error) { + err := ValidateChannelValues(channel) + if err != nil { + return nil, err + } + + path := fmt.Sprintf("channels/%s", channel.ID) + resp, err := apiUpdate(s.sling, channel, new(Channel), path) + + if err != nil { + return nil, err + } + + return resp.(*Channel), nil +} diff --git a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/machines.go b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/machines.go index 800159d7e..e3a673b8f 100644 --- a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/machines.go +++ b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/machines.go @@ -42,15 +42,27 @@ type Machine struct { LastModifiedBy *string `json:"LastModifiedBy,omitempty"` } +type MachineEndpointAuthentication struct { + AccountID string `json:"AccountId"` + ClientCertificate string `json:"ClientCertificate"` + AuthenticationType string `json:"AuthenticationType"` +} + type MachineEndpoint struct { - ID string `json:"Id"` - CommunicationStyle string `json:"CommunicationStyle"` - ProxyID *string `json:"ProxyId"` - Thumbprint string `json:"Thumbprint"` - TentacleVersionDetails MachineTentacleVersionDetails `json:"TentacleVersionDetails"` - LastModifiedOn *string `json:"LastModifiedOn,omitempty"` - LastModifiedBy *string `json:"LastModifiedBy,omitempty"` - URI string `json:"Uri"` //This is not in the spec doc, but it shows up and needs to be kept in sync + ID string `json:"Id"` + CommunicationStyle string `json:"CommunicationStyle"` + ProxyID *string `json:"ProxyId"` + Thumbprint string `json:"Thumbprint"` + TentacleVersionDetails MachineTentacleVersionDetails `json:"TentacleVersionDetails"` + LastModifiedOn *string `json:"LastModifiedOn,omitempty"` + LastModifiedBy *string `json:"LastModifiedBy,omitempty"` + URI string `json:"Uri"` // This is not in the spec doc, but it shows up and needs to be kept in sync + ClusterCertificate string `json:"ClusterCertificate"` // Kubernetes (not in spec doc) + ClusterURL string `json:"ClusterUrl"` // Kubernetes (not in spec doc) + Namespace string `json:"Namespace"` // Kubernetes (not in spec doc) + SkipTLSVerification string `json:"SkipTlsVerification"` // Kubernetes (not in spec doc) + DefaultWorkerPoolID string `json:"DefaultWorkerPoolId"` + Authentication *MachineEndpointAuthentication `json:"Authentication"` } type MachineTentacleVersionDetails struct { @@ -130,6 +142,24 @@ func (s *MachineService) GetAll() (*[]Machine, error) { return &p, nil } +// GetByName gets an existing machine by its name in Octopus Deploy +func (s *MachineService) GetByName(machineName string) (*Machine, error) { + var found Machine + machines, err := s.GetAll() + + if err != nil { + return nil, err + } + + for _, machine := range *machines { + if machine.Name == machineName { + return &machine, nil + } + } + + return &found, fmt.Errorf("no machine found with name %s", machineName) +} + // Add creates a new machine in Octopus Deploy func (s *MachineService) Add(machine *Machine) (*Machine, error) { err := ValidateMachineValues(machine) diff --git a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/octopusdeploy.go b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/octopusdeploy.go index 82370295c..91d3ed36a 100644 --- a/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/octopusdeploy.go +++ b/vendor/github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy/octopusdeploy.go @@ -29,6 +29,7 @@ type Client struct { Interruption *InterruptionsService TagSet *TagSetService Space *SpaceService + Channel *ChannelService } // NewClient returns a new Client. @@ -55,6 +56,7 @@ func NewClient(httpClient *http.Client, octopusURL, octopusAPIKey string) *Clien Interruption: NewInterruptionService(base.New()), TagSet: NewTagSetService(base.New()), Space: NewSpaceService(base.New()), + Channel: NewChannelService(base.New()), } } @@ -79,6 +81,7 @@ func ForSpace(httpClient *http.Client, octopusURL, octopusAPIKey string, space * Lifecycle: NewLifecycleService(base.New()), LibraryVariableSet: NewLibraryVariableSetService(base.New()), TagSet: NewTagSetService(base.New()), + Channel: NewChannelService(base.New()), } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 85b01c1b6..639179401 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/OctopusDeploy/go-octopusdeploy v1.3.0 +# github.com/OctopusDeploy/go-octopusdeploy v1.4.0 github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy # github.com/agext/levenshtein v1.2.1 github.com/agext/levenshtein