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 workers data source #818

Merged
merged 9 commits into from
Nov 19, 2024
70 changes: 70 additions & 0 deletions docs/data-sources/workers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "octopusdeploy_workers Data Source - terraform-provider-octopusdeploy"
subcategory: ""
description: |-
Provides information about existing workers.
---

# octopusdeploy_workers (Data Source)

Provides information about existing workers.

## Example Usage

```terraform
data "octopusdeploy_workers" "example" {
communication_styles = ["TentaclePassive"]
health_statuses = ["Unavailable"]
ids = ["Workers-123"]
name = "Exact name"
partial_name = "Test"
skip = 5
take = 100
is_disabled = true
}
```

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

### Optional

- `communication_styles` (List of String) A filter to search by communication styles
- `health_statuses` (List of String) A filter to search by health statuses
- `ids` (List of String) A filter to search by a list of IDs.
- `is_disabled` (Boolean)
- `name` (String) The name of this resource.
- `partial_name` (String) A filter to search by a partial name.
- `skip` (Number) A filter to specify the number of items to skip in the response.
- `space_id` (String) The space ID associated with this workers.
- `take` (Number) A filter to specify the number of items to take (or return) in the response.

### Read-Only

- `id` (String) The unique ID for this resource.
- `workers` (Attributes List) (see [below for nested schema](#nestedatt--workers))

<a id="nestedatt--workers"></a>
### Nested Schema for `workers`

Read-Only:

- `account_id` (String)
- `communication_style` (String)
- `dotnet_platform` (String)
- `fingerprint` (String)
- `health_status` (String)
- `host` (String)
- `id` (String) The unique ID for this resource.
- `is_disabled` (Boolean)
- `machine_policy_id` (String)
- `name` (String) The name of this resource.
- `port` (Number)
- `proxy_id` (String)
- `space_id` (String) The space ID associated with this workers.
- `thumbprint` (String)
- `uri` (String)
- `worker_pool_ids` (List of String)


10 changes: 10 additions & 0 deletions examples/data-sources/octopusdeploy_workers/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
data "octopusdeploy_workers" "example" {
communication_styles = ["TentaclePassive"]
health_statuses = ["Unavailable"]
ids = ["Workers-123"]
name = "Exact name"
partial_name = "Test"
skip = 5
take = 100
is_disabled = true
}
72 changes: 72 additions & 0 deletions octopusdeploy_framework/datasource_workers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package octopusdeploy_framework

import (
"context"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workers"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/types"
"time"
)

type workersDataSource struct {
*Config
}

func NewWorkersDataSource() datasource.DataSource {
return &workersDataSource{}
}

func (*workersDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = util.GetTypeName("workers")
}

func (e *workersDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
e.Config = DataSourceConfiguration(req, resp)
}

func (*workersDataSource) Schema(_ context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schemas.WorkersSchema{}.GetDatasourceSchema()
}

func (e *workersDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var err error
var data schemas.WorkersDataSourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

query := machines.WorkersQuery{
Name: data.Name.ValueString(),
IDs: util.GetIds(data.IDs),
PartialName: data.PartialName.ValueString(),
Skip: util.GetNumber(data.Skip),
Take: util.GetNumber(data.Take),
CommunicationStyles: util.ExpandStringList(data.CommunicationStyle),
HealthStatuses: util.ExpandStringList(data.HealthStatuses),
IsDisabled: data.IsDisabled.ValueBool(),
}

util.DatasourceReading(ctx, "workers", query)

existingWorkers, err := workers.Get(e.Client, data.SpaceID.ValueString(), query)
if err != nil {
resp.Diagnostics.AddError("unable to load workers", err.Error())
return
}

util.DatasourceResultCount(ctx, "workers", len(existingWorkers.Items))

resources := []interface{}{}
for _, worker := range existingWorkers.Items {
resources = append(resources, schemas.FlattenWorker(worker))
}

data.Workers, _ = types.ListValueFrom(ctx, types.ObjectType{AttrTypes: schemas.WorkerObjectType()}, resources)
data.ID = types.StringValue("Workers " + time.Now().UTC().String())

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

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/acctest"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

func TestAccDataSourceWorkers(t *testing.T) {
localName := acctest.RandStringFromCharSet(50, acctest.CharSetAlpha)
prefix := fmt.Sprintf("data.octopusdeploy_workers.%s", localName)
sshFilter := `communication_styles = ["Ssh"]`
listeningFilter := `communication_styles = ["TentaclePassive"]`

resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: ProtoV6ProviderFactories(),
PreCheck: func() { TestAccPreCheck(t) },
Steps: []resource.TestStep{
{
Config: configTestAccDataSourceWorkerResources(localName, ""),
},
{
Config: configTestAccDataSourceWorkerResources(localName, ""),
Check: testAssertDataSourceWorkersEmpty(prefix),
},
{
Config: configTestAccDataSourceWorkerResources(localName, sshFilter),
Check: testAssertDataSourceSSHWorkers(prefix),
},
{
Config: configTestAccDataSourceWorkerResources(localName, listeningFilter),
Check: testAssertDataSourceListeningWorkers(prefix),
},
},
})
}

func testAssertDataSourceWorkersEmpty(prefix string) resource.TestCheckFunc {
return resource.ComposeTestCheckFunc(
testAssertWorkersDataSourceID(prefix),
resource.TestCheckResourceAttr(prefix, "workers.#", "2"),
)
}

func testAssertDataSourceSSHWorkers(prefix string) resource.TestCheckFunc {
return resource.ComposeTestCheckFunc(
testAssertWorkersDataSourceID(prefix),
resource.TestCheckResourceAttr(prefix, "workers.#", "1"),
resource.TestCheckResourceAttr(prefix, "workers.0.name", "First SSH worker"),
resource.TestCheckResourceAttr(prefix, "workers.0.host", "test.domain"),
resource.TestCheckResourceAttr(prefix, "workers.0.port", "4201"),
resource.TestCheckResourceAttr(prefix, "workers.0.fingerprint", "SHA256: 1234abcdef56789"),
resource.TestCheckResourceAttr(prefix, "workers.0.dotnet_platform", "linux-x64"),
)
}

func testAssertDataSourceListeningWorkers(prefix string) resource.TestCheckFunc {
return resource.ComposeTestCheckFunc(
testAssertWorkersDataSourceID(prefix),
resource.TestCheckResourceAttr(prefix, "workers.#", "1"),
resource.TestCheckResourceAttr(prefix, "workers.0.name", "Second listening worker"),
resource.TestCheckResourceAttr(prefix, "workers.0.uri", "https://domain.test/"),
resource.TestCheckResourceAttr(prefix, "workers.0.thumbprint", "abcdef"),
)
}

func testAssertWorkersDataSourceID(prefix string) resource.TestCheckFunc {
return func(s *terraform.State) error {
all := s.RootModule().Resources
dataSource, ok := all[prefix]
if !ok {
return fmt.Errorf("cannot find Workers data source: %s", prefix)
}

if dataSource.Primary.ID == "" {
return fmt.Errorf("snapshot Workers source ID not set")
}
return nil
}
}

func configTestAccDataSourceWorkerResources(localName string, dataSourceFilter string) string {
return fmt.Sprintf(`
resource "octopusdeploy_machine_policy" "policy_1" {
name = "Machine Policy One"
}

resource "octopusdeploy_static_worker_pool" "pool_1" {
name = "Worker Pool One"
description = "First pool of listening workers"
sort_order = 99
}

resource "octopusdeploy_ssh_key_account" "account_1" {
name = "SSH Key Pair Account"
private_key_file = "[private_key_file]"
username = "[username]"
}

resource "octopusdeploy_ssh_connection_worker" "worker_1" {
name = "First SSH worker"
machine_policy_id = octopusdeploy_machine_policy.policy_1.id
worker_pool_ids = [octopusdeploy_static_worker_pool.pool_1.id]
account_id = octopusdeploy_ssh_key_account.account_1.id
host = "test.domain"
port = 4201
fingerprint = "SHA256: 1234abcdef56789"
dotnet_platform = "linux-x64"
}

resource "octopusdeploy_listening_tentacle_worker" "worker_2" {
name = "Second listening worker"
machine_policy_id = octopusdeploy_machine_policy.policy_1.id
worker_pool_ids = [octopusdeploy_static_worker_pool.pool_1.id]
uri = "https://domain.test/"
thumbprint = "abcdef"
}

data "octopusdeploy_workers" "%s" {
%s
}
`,
localName,
dataSourceFilter,
)
}
1 change: 1 addition & 0 deletions octopusdeploy_framework/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func (p *octopusDeployFrameworkProvider) DataSources(ctx context.Context) []func
NewScriptModuleDataSource,
NewTenantProjectDataSource,
NewUsersDataSource,
NewWorkersDataSource,
}
}

Expand Down
Loading
Loading