Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add listening tentacle worker #812

Merged
merged 11 commits into from
Nov 13, 2024
Merged
6 changes: 3 additions & 3 deletions docs/resources/azure_container_registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
page_title: "octopusdeploy_azure_container_registry Resource - terraform-provider-octopusdeploy"
subcategory: ""
description: |-
This resource manages a Google Container Registry feed in Octopus Deploy (alias of Docker Container Registry feed)
This resource manages Azure Container Registry feed in Octopus Deploy (alias of Docker Container Registry feed)
---

# octopusdeploy_azure_container_registry (Resource)

This resource manages a Google Container Registry feed in Octopus Deploy (alias of Docker Container Registry feed)
This resource manages Azure Container Registry feed in Octopus Deploy (alias of Docker Container Registry feed)

## Example Usage

Expand All @@ -34,7 +34,7 @@ resource "octopusdeploy_azure_container_registry" "example" {
- `api_version` (String)
- `password` (String, Sensitive) The password associated with this resource.
- `registry_path` (String)
- `space_id` (String) The space ID associated with this Google container registry feed.
- `space_id` (String) The space ID associated with this Azure container registry feed.
- `username` (String, Sensitive) The username associated with this resource.

### Read-Only
Expand Down
62 changes: 62 additions & 0 deletions docs/resources/listening_tentacle_worker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "octopusdeploy_listening_tentacle_worker Resource - terraform-provider-octopusdeploy"
subcategory: ""
description: |-
This resource manages a listening tentacle worker in Octopus Deploy.
---

# octopusdeploy_listening_tentacle_worker (Resource)

This resource manages a listening tentacle worker in Octopus Deploy.

## Example Usage

```terraform
resource "octopusdeploy_listening_tentacle_worker" "minimum" {
name = "listening_worker"
machine_policy_id = "machine-policy-1"
worker_pools = ["worker-pools-1", "worker-pools-2"]
thumbprint = "96203ED84246201C26A2F4360D7CBC36AC1D232D"
uri = "https://tentacle.listening/"
}

resource "octopusdeploy_listening_tentacle_worker" "optionals" {
name = "optional_worker"
machine_policy_id = "machine-policy-1"
worker_pools = ["worker-pools-1"]
thumbprint = "96203ED84246201C26A2F4360D7CBC36AC1D232D"
uri = "https://tentacle.listening/"
proxy_id = "proxys-1"
is_disabled = true
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `machine_policy_id` (String) Select the machine policy
- `name` (String) The name of this resource.
- `thumbprint` (String) The X509 certificate thumbprint that securely identifies the Tentacle
- `uri` (String) The network address at which the Tentacle can be reached
- `worker_pool_ids` (Set of String) Select at least one worker pool for the worker

### Optional

- `is_disabled` (Boolean) When disabled, worker will not be included in any deployments
- `proxy_id` (String) Specify the connection type for the Tentacle: direct(when not set) or via a proxy server.
- `space_id` (String) The space ID associated with this Listening tentacle worker.

### Read-Only

- `id` (String) The unique ID for this resource.

## Import

Import is supported using the following syntax:

```shell
terraform import [options] octopusdeploy_listening_tentacle_worker.<name> <machine-id>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import [options] octopusdeploy_listening_tentacle_worker.<name> <machine-id>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource "octopusdeploy_listening_tentacle_worker" "minimum" {
name = "listening_worker"
machine_policy_id = "machine-policy-1"
worker_pools = ["worker-pools-1", "worker-pools-2"]
thumbprint = "96203ED84246201C26A2F4360D7CBC36AC1D232D"
uri = "https://tentacle.listening/"
}

resource "octopusdeploy_listening_tentacle_worker" "optionals" {
name = "optional_worker"
machine_policy_id = "machine-policy-1"
worker_pools = ["worker-pools-1"]
thumbprint = "96203ED84246201C26A2F4360D7CBC36AC1D232D"
uri = "https://tentacle.listening/"
proxy_id = "proxys-1"
is_disabled = true
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,5 @@ require (
google.golang.org/protobuf v1.34.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)


1 change: 1 addition & 0 deletions octopusdeploy_framework/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func (p *octopusDeployFrameworkProvider) Resources(ctx context.Context) []func()
NewRunbookResource,
NewTenantResource,
NewTentacleCertificateResource,
NewListeningTentacleWorkerResource,
NewScriptModuleResource,
NewUserResource,
}
Expand Down
4 changes: 2 additions & 2 deletions octopusdeploy_framework/resource_azure_container_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (r *azureContainerRegistryFeedTypeResource) Metadata(ctx context.Context, r
}

func (r *azureContainerRegistryFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schemas.GoogleContainerRegistryFeedSchema{}.GetResourceSchema()
resp.Schema = schemas.AzureContainerRegistryFeedSchema{}.GetResourceSchema()
}

func (r *azureContainerRegistryFeedTypeResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
Expand Down Expand Up @@ -117,7 +117,7 @@ func (r *azureContainerRegistryFeedTypeResource) Update(ctx context.Context, req

updateAzureDataFromDockerContainerRegistryFeed(data, state.SpaceID.ValueString(), updatedFeed.(*feeds.DockerContainerRegistry))

tflog.Info(ctx, fmt.Sprintf("Google Container Registry feed updated (%s)", data.ID))
tflog.Info(ctx, fmt.Sprintf("Azure Container Registry feed updated (%s)", data.ID))

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
Expand Down
174 changes: 174 additions & 0 deletions octopusdeploy_framework/resource_listening_tentacle_worker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package octopusdeploy_framework

import (
"context"
"fmt"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workers"
"github.com/hashicorp/terraform-plugin-framework/path"
"net/url"

"github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal/errors"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

type listeningTentacleWorkerResource struct {
*Config
}

func NewListeningTentacleWorkerResource() resource.Resource {
return &listeningTentacleWorkerResource{}
}

var _ resource.ResourceWithImportState = &listeningTentacleWorkerResource{}

func (r *listeningTentacleWorkerResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = util.GetTypeName("listening_tentacle_worker")
}

func (r *listeningTentacleWorkerResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schemas.ListeningTentacleWorkerSchema{}.GetResourceSchema()
}

func (r *listeningTentacleWorkerResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
r.Config = ResourceConfiguration(req, resp)
}

func (r *listeningTentacleWorkerResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data *schemas.ListeningTentacleWorkerResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

worker := createListeningTentacleWorkerResource(ctx, data)

tflog.Info(ctx, fmt.Sprintf("creating listening tentacle worker: %s", data.Name.ValueString()))

client := r.Config.Client
createdWorker, err := workers.Add(client, worker)
if err != nil {
resp.Diagnostics.AddError("unable to create listening tentacle worker", err.Error())
return
}

updateDataFromListeningTentacleWorker(ctx, data, data.SpaceID.ValueString(), createdWorker)

tflog.Info(ctx, fmt.Sprintf("listening tentacle worker created (%s)", data.ID))
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *listeningTentacleWorkerResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data *schemas.ListeningTentacleWorkerResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

tflog.Info(ctx, fmt.Sprintf("reading listening tentacle worker (%s)", data.ID))

client := r.Config.Client
worker, err := workers.GetByID(client, data.SpaceID.ValueString(), data.ID.ValueString())
if err != nil {
if err := errors.ProcessApiErrorV2(ctx, resp, data, err, "listening tentacle worker"); err != nil {
resp.Diagnostics.AddError("unable to load listening tentacle worker", err.Error())
}
return
}

if worker.Endpoint.GetCommunicationStyle() != "TentaclePassive" {
resp.Diagnostics.AddError("unable to load listening tentacle worker", "found resource is not listening tentacle worker")
return
}

updateDataFromListeningTentacleWorker(ctx, data, data.SpaceID.ValueString(), worker)

tflog.Info(ctx, fmt.Sprintf("listening tentacle worker read (%s)", worker.GetID()))
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *listeningTentacleWorkerResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data, state *schemas.ListeningTentacleWorkerResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

tflog.Debug(ctx, fmt.Sprintf("updating listening tentacle worker '%s'", data.ID.ValueString()))

worker := createListeningTentacleWorkerResource(ctx, data)
worker.ID = state.ID.ValueString()

tflog.Info(ctx, fmt.Sprintf("updating listening tentacle worker (%s)", data.ID))

client := r.Config.Client
updatedWorker, err := workers.Update(client, worker)
if err != nil {
resp.Diagnostics.AddError("unable to update listening tentacle worker", err.Error())
return
}

updateDataFromListeningTentacleWorker(ctx, data, state.SpaceID.ValueString(), updatedWorker)

tflog.Info(ctx, fmt.Sprintf("listening tentacle worker updated (%s)", data.ID))

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *listeningTentacleWorkerResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data schemas.ListeningTentacleWorkerResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

if err := workers.DeleteByID(r.Config.Client, data.SpaceID.ValueString(), data.ID.ValueString()); err != nil {
resp.Diagnostics.AddError("unable to delete listening tentacle worker", err.Error())
return
}
}

func createListeningTentacleWorkerResource(ctx context.Context, data *schemas.ListeningTentacleWorkerResourceModel) *machines.Worker {
uri, _ := url.Parse(data.Uri.ValueString())
endpoint := machines.NewListeningTentacleEndpoint(uri, data.Thumbprint.ValueString())
endpoint.ProxyID = data.ProxyID.ValueString()

worker := machines.NewWorker(data.Name.ValueString(), endpoint)
worker.SpaceID = data.SpaceID.ValueString()
worker.IsDisabled = data.IsDisabled.ValueBool()
worker.MachinePolicyID = data.MachinePolicyID.ValueString()

if !data.WorkerPoolIDs.IsNull() {
var workerPools []string
data.WorkerPoolIDs.ElementsAs(ctx, &workerPools, false)
worker.WorkerPoolIDs = workerPools
}

return worker
}

func updateDataFromListeningTentacleWorker(ctx context.Context, data *schemas.ListeningTentacleWorkerResourceModel, spaceId string, worker *machines.Worker) {
data.ID = types.StringValue(worker.ID)
data.SpaceID = types.StringValue(spaceId)
data.Name = types.StringValue(worker.Name)
data.IsDisabled = types.BoolValue(worker.IsDisabled)
data.MachinePolicyID = types.StringValue(worker.MachinePolicyID)
data.WorkerPoolIDs, _ = types.SetValueFrom(ctx, types.StringType, worker.WorkerPoolIDs)

endpoint := worker.Endpoint.(*machines.ListeningTentacleEndpoint)
data.Uri = types.StringValue(endpoint.URI.String())
data.Thumbprint = types.StringValue(endpoint.Thumbprint)
if endpoint.ProxyID != "" {
data.ProxyID = types.StringValue(endpoint.ProxyID)
}
}

func (*listeningTentacleWorkerResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}
Loading
Loading