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 workload identity support #206

Merged
merged 19 commits into from
Feb 18, 2025
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ Ensure you have the following installed:
export ASTRO_API_TOKEN=<your-api-token>
```

### Setting up the Import script for Local Development

1. Build the import script from the import directory
```
go build import_script.go
```
2. Run the import script
```
./import_script -resources deployment -organizationId <your-org-id> -host dev -token YOU_API_TOKEN
```

## Making Changes

1. Create a new branch for your changes:
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ resource "astro_deployment" "dedicated" {
resource_quota_memory = "20Gi"
scheduler_size = "SMALL"
workspace_id = "clnp86ly5000401ndaga21g81"
desired_workload_identity = "arn:aws:iam::123456789:role/AirflowS3Logs-clmk2qqia000008mhff3ndjr0"
environment_variables = [{
key = "key1"
value = "value1"
Expand Down Expand Up @@ -164,6 +165,7 @@ resource "astro_deployment" "imported_deployment" {
- `cluster_id` (String) Deployment cluster identifier - required for 'HYBRID' and 'DEDICATED' deployments. If changing this value, the deployment will be recreated in the new cluster
- `default_task_pod_cpu` (String) Deployment default task pod CPU - required for 'STANDARD' and 'DEDICATED' deployments
- `default_task_pod_memory` (String) Deployment default task pod memory - required for 'STANDARD' and 'DEDICATED' deployments
- `desired_workload_identity` (String) Deployment's desired workload identity. The Terraform provider will use this provided workload identity to create the Deployment. If it is not provided the workload identity will be assigned automatically.
- `is_development_mode` (Boolean) Deployment development mode - required for 'STANDARD' and 'DEDICATED' deployments. If changing from 'False' to 'True', the deployment will be recreated
- `is_high_availability` (Boolean) Deployment high availability - required for 'STANDARD' and 'DEDICATED' deployments
- `original_astro_runtime_version` (String) Deployment's original Astro Runtime version. The Terraform provider will use this provided Astro runtime version to create the Deployment. The Astro runtime version can be updated with your Astro project Dockerfile, but if this value is changed, the Deployment will be recreated with this new Astro runtime version.
Expand Down
1 change: 1 addition & 0 deletions examples/resources/astro_deployment/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ resource "astro_deployment" "dedicated" {
resource_quota_memory = "20Gi"
scheduler_size = "SMALL"
workspace_id = "clnp86ly5000401ndaga21g81"
desired_workload_identity = "arn:aws:iam::123456789:role/AirflowS3Logs-clmk2qqia000008mhff3ndjr0"
environment_variables = [{
key = "key1"
value = "value1"
Expand Down
10 changes: 10 additions & 0 deletions import/import_script.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,12 @@ func generateDeploymentHCL(ctx context.Context, platformClient *platform.ClientW

deploymentType := deployment.Type

workloadIdentity := deployment.WorkloadIdentity
workloadIdentityString := ""
if workloadIdentity != nil {
workloadIdentityString = fmt.Sprintf(`desired_workload_identity = "%s"`, *workloadIdentity)
}

if *deploymentType == platform.DeploymentTypeDEDICATED {
deploymentHCL = fmt.Sprintf(`
resource "astro_deployment" "deployment_%s" {
Expand All @@ -845,6 +851,7 @@ resource "astro_deployment" "deployment_%s" {
type = "%s"
workspace_id = "%s"
%s
%s
}
`,
deployment.Id,
Expand All @@ -866,6 +873,7 @@ resource "astro_deployment" "deployment_%s" {
stringValue((*string)(deploymentType)),
deployment.WorkspaceId,
workerQueuesString,
workloadIdentityString,
)
} else if *deploymentType == platform.DeploymentTypeSTANDARD {
deploymentHCL = fmt.Sprintf(`
Expand All @@ -889,6 +897,7 @@ resource "astro_deployment" "deployment_%s" {
type = "%s"
workspace_id = "%s"
%s
%s
}
`,
deployment.Id,
Expand All @@ -911,6 +920,7 @@ resource "astro_deployment" "deployment_%s" {
stringValue((*string)(deploymentType)),
deployment.WorkspaceId,
workerQueuesString,
workloadIdentityString,
)
} else {
log.Printf("Skipping deployment %s: unsupported deployment type %s", deployment.Id, stringValue((*string)(deploymentType)))
Expand Down
1 change: 1 addition & 0 deletions internal/provider/models/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type DeploymentResource struct {
DesiredDagTarballVersion types.String `tfsdk:"desired_dag_tarball_version"`
IsCicdEnforced types.Bool `tfsdk:"is_cicd_enforced"`
IsDagDeployEnabled types.Bool `tfsdk:"is_dag_deploy_enabled"`
DesiredWorkloadIdentity types.String `tfsdk:"desired_workload_identity"`
WorkloadIdentity types.String `tfsdk:"workload_identity"`
ExternalIps types.Set `tfsdk:"external_ips"`
OidcIssuerUrl types.String `tfsdk:"oidc_issuer_url"`
Expand Down
26 changes: 26 additions & 0 deletions internal/provider/resources/resource_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ func (r *DeploymentResource) Create(
}
}

desiredWorkloadIdentity := data.DesiredWorkloadIdentity.ValueString()

switch data.Type.ValueString() {
case string(platform.DeploymentTypeSTANDARD):
createStandardDeploymentRequest := platform.CreateStandardDeploymentRequest{
Expand All @@ -127,6 +129,9 @@ func (r *DeploymentResource) Create(
Type: platform.CreateStandardDeploymentRequestTypeSTANDARD,
WorkspaceId: data.WorkspaceId.ValueString(),
}
if desiredWorkloadIdentity != "" {
createStandardDeploymentRequest.WorkloadIdentity = &desiredWorkloadIdentity
}

// contact emails
contactEmails, diags := utils.TypesSetToStringSlice(ctx, data.ContactEmails)
Expand Down Expand Up @@ -187,6 +192,9 @@ func (r *DeploymentResource) Create(
Type: platform.CreateDedicatedDeploymentRequestTypeDEDICATED,
WorkspaceId: data.WorkspaceId.ValueString(),
}
if desiredWorkloadIdentity != "" {
createDedicatedDeploymentRequest.WorkloadIdentity = &desiredWorkloadIdentity
}

// contact emails
contactEmails, diags := utils.TypesSetToStringSlice(ctx, data.ContactEmails)
Expand Down Expand Up @@ -246,6 +254,10 @@ func (r *DeploymentResource) Create(
WorkspaceId: data.WorkspaceId.ValueString(),
}

if desiredWorkloadIdentity != "" {
createHybridDeploymentRequest.WorkloadIdentity = &desiredWorkloadIdentity
}

// contact emails
contactEmails, diags := utils.TypesSetToStringSlice(ctx, data.ContactEmails)
createHybridDeploymentRequest.ContactEmails = &contactEmails
Expand Down Expand Up @@ -386,6 +398,8 @@ func (r *DeploymentResource) Update(
var updateDeploymentRequest platform.UpdateDeploymentRequest
var envVars []platform.DeploymentEnvironmentVariableRequest

desiredWorkloadIdentity := data.DesiredWorkloadIdentity.ValueString()

switch data.Type.ValueString() {
case string(platform.DeploymentTypeSTANDARD):
updateStandardDeploymentRequest := platform.UpdateStandardDeploymentRequest{
Expand All @@ -405,6 +419,10 @@ func (r *DeploymentResource) Update(
WorkspaceId: data.WorkspaceId.ValueString(),
}

if desiredWorkloadIdentity != "" {
updateStandardDeploymentRequest.WorkloadIdentity = &desiredWorkloadIdentity
}

// contact emails
contactEmails, diags := utils.TypesSetToStringSlice(ctx, data.ContactEmails)
updateStandardDeploymentRequest.ContactEmails = &contactEmails
Expand Down Expand Up @@ -463,6 +481,10 @@ func (r *DeploymentResource) Update(
WorkspaceId: data.WorkspaceId.ValueString(),
}

if desiredWorkloadIdentity != "" {
updateDedicatedDeploymentRequest.WorkloadIdentity = &desiredWorkloadIdentity
}

// contact emails
contactEmails, diags := utils.TypesSetToStringSlice(ctx, data.ContactEmails)
updateDedicatedDeploymentRequest.ContactEmails = &contactEmails
Expand Down Expand Up @@ -519,6 +541,10 @@ func (r *DeploymentResource) Update(
WorkspaceId: data.WorkspaceId.ValueString(),
}

if desiredWorkloadIdentity != "" {
updateHybridDeploymentRequest.WorkloadIdentity = &desiredWorkloadIdentity
}

// contact emails
contactEmails, diags := utils.TypesSetToStringSlice(ctx, data.ContactEmails)
updateHybridDeploymentRequest.ContactEmails = &contactEmails
Expand Down
20 changes: 18 additions & 2 deletions internal/provider/resources/resource_deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,15 @@ func TestAcc_ResourceDeploymentHybrid(t *testing.T) {
IncludeEnvironmentVariables: false,
SchedulerAu: 6,
NodePoolId: nodePoolId,
DesiredWorkloadIdentity: "arn:aws:iam::123456789:role/AirflowS3Logs-clmk2qqia000008mhff3ndjr0",
}),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceVar, "description", utils.TestResourceDescription),
resource.TestCheckResourceAttr(resourceVar, "worker_queues.0.name", "default"),
resource.TestCheckResourceAttr(resourceVar, "environment_variables.#", "0"),
resource.TestCheckResourceAttr(resourceVar, "executor", "CELERY"),
resource.TestCheckResourceAttr(resourceVar, "scheduler_au", "6"),
resource.TestCheckResourceAttr(resourceVar, "workload_identity", "arn:aws:iam::123456789:role/AirflowS3Logs-clmk2qqia000008mhff3ndjr0"),
// Check via API that deployment exists
testAccCheckDeploymentExistence(t, deploymentName, false, true),
),
Expand Down Expand Up @@ -194,13 +196,15 @@ func TestAcc_ResourceDeploymentStandard(t *testing.T) {
SchedulerSize: string(platform.SchedulerMachineNameEXTRALARGE),
IncludeEnvironmentVariables: false,
WorkerQueuesStr: workerQueuesStr(""),
DesiredWorkloadIdentity: "arn:aws:iam::123456789:role/AirflowS3Logs-clmk2qqia000008mhff3ndjr0",
}),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(awsResourceVar, "description", utils.TestResourceDescription),
resource.TestCheckResourceAttr(awsResourceVar, "scheduler_size", string(platform.SchedulerMachineNameEXTRALARGE)),
resource.TestCheckResourceAttr(awsResourceVar, "worker_queues.0.name", "default"),
resource.TestCheckNoResourceAttr(awsResourceVar, "environment_variables.0.key"),
resource.TestCheckResourceAttr(awsResourceVar, "executor", "CELERY"),
resource.TestCheckResourceAttr(awsResourceVar, "workload_identity", "arn:aws:iam::123456789:role/AirflowS3Logs-clmk2qqia000008mhff3ndjr0"),
// Check via API that deployment exists
testAccCheckDeploymentExistence(t, awsDeploymentName, true, true),
),
Expand Down Expand Up @@ -722,6 +726,7 @@ type hybridDeploymentInput struct {
SchedulerAu int
NodePoolId string
DuplicateWorkerQueues bool
DesiredWorkloadIdentity string
}

func hybridDeployment(input hybridDeploymentInput) string {
Expand All @@ -736,6 +741,10 @@ func hybridDeployment(input hybridDeploymentInput) string {
} else {
taskPodNodePoolIdStr = fmt.Sprintf(`task_pod_node_pool_id = "%v"`, input.NodePoolId)
}
desiredWorkloadIdentityStr := ""
if input.DesiredWorkloadIdentity != "" {
desiredWorkloadIdentityStr = input.DesiredWorkloadIdentity
}

return fmt.Sprintf(`
resource "astro_workspace" "%v_workspace" {
Expand All @@ -758,12 +767,13 @@ resource "astro_deployment" "%v" {
%v
%v
%v
%v
}
`,
input.Name, input.Name, utils.TestResourceDescription,
input.Name, input.Name, utils.TestResourceDescription,
input.ClusterId, input.Executor, input.SchedulerAu, input.Name,
envVarsStr(input.IncludeEnvironmentVariables), wqStr, taskPodNodePoolIdStr)
envVarsStr(input.IncludeEnvironmentVariables), wqStr, taskPodNodePoolIdStr, desiredWorkloadIdentityStr)
}

func developmentDeployment(scalingSpecDeploymentName, scalingSpec string) string {
Expand Down Expand Up @@ -791,6 +801,7 @@ type standardDeploymentInput struct {
IsDevelopmentMode bool
ScalingSpec string
WorkerQueuesStr string
DesiredWorkloadIdentity string
}

func standardDeployment(input standardDeploymentInput) string {
Expand All @@ -816,6 +827,10 @@ func standardDeployment(input standardDeploymentInput) string {
scalingSpecStr = input.ScalingSpec
}
}
desiredWorkloadIdentityStr := ""
if input.DesiredWorkloadIdentity != "" {
desiredWorkloadIdentityStr = input.DesiredWorkloadIdentity
}
return fmt.Sprintf(`
resource "astro_workspace" "%v_workspace" {
name = "%s"
Expand Down Expand Up @@ -844,10 +859,11 @@ resource "astro_deployment" "%v" {
%v
%v
%v
%v
}
`,
input.Name, input.Name, utils.TestResourceDescription, input.Name, input.Name, input.Description, input.Region, input.CloudProvider, input.Executor, input.IsDevelopmentMode, input.SchedulerSize, input.Name,
envVarsStr(input.IncludeEnvironmentVariables), input.WorkerQueuesStr, scalingSpecStr)
envVarsStr(input.IncludeEnvironmentVariables), input.WorkerQueuesStr, scalingSpecStr, desiredWorkloadIdentityStr)
}

func standardDeploymentWithVariableName(input standardDeploymentInput) string {
Expand Down
4 changes: 4 additions & 0 deletions internal/provider/schemas/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ func DeploymentResourceSchemaAttributes() map[string]resourceSchema.Attribute {
stringplanmodifier.UseStateForUnknown(),
},
},
"desired_workload_identity": resourceSchema.StringAttribute{
MarkdownDescription: "Deployment's desired workload identity. The Terraform provider will use this provided workload identity to create the Deployment. If it is not provided the workload identity will be assigned automatically.",
Optional: true,
},
"workload_identity": resourceSchema.StringAttribute{
MarkdownDescription: "Deployment workload identity. This value can be changed via the Astro API if applicable.",
Computed: true,
Expand Down
Loading