diff --git a/docs/data-sources/git_repository.md b/docs/data-sources/git_repository.md index 85af1c2..fb70662 100644 --- a/docs/data-sources/git_repository.md +++ b/docs/data-sources/git_repository.md @@ -3,12 +3,12 @@ page_title: "plural_git_repository Data Source - terraform-provider-plural" subcategory: "" description: |- - GitRepository resource + Git repository data source. --- # plural_git_repository (Data Source) -GitRepository resource +Git repository data source. @@ -17,5 +17,5 @@ GitRepository resource ### Optional -- `id` (String) Internal identifier of this GitRepository. -- `url` (String) URL of this GitRepository. +- `id` (String) Internal identifier of this Git repository. +- `url` (String) URL of this Git repository. diff --git a/docs/data-sources/infrastructure_stack.md b/docs/data-sources/infrastructure_stack.md new file mode 100644 index 0000000..346e0e5 --- /dev/null +++ b/docs/data-sources/infrastructure_stack.md @@ -0,0 +1,28 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "plural_infrastructure_stack Data Source - terraform-provider-plural" +subcategory: "" +description: |- + Stack data source. +--- + +# plural_infrastructure_stack (Data Source) + +Stack data source. + + + + +## Schema + +### Optional + +- `id` (String) Internal identifier of this stack. +- `name` (String) Human-readable name of this stack. + +### Read-Only + +- `approval` (Boolean) Determines whether to require approval. +- `cluster_id` (String) The cluster on which the stack is be applied. +- `project_id` (String) ID of the project that this stack belongs to. +- `type` (String) A type for the stack, specifies the tool to use to apply it. diff --git a/docs/data-sources/pr_automation.md b/docs/data-sources/pr_automation.md new file mode 100644 index 0000000..810613d --- /dev/null +++ b/docs/data-sources/pr_automation.md @@ -0,0 +1,27 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "plural_pr_automation Data Source - terraform-provider-plural" +subcategory: "" +description: |- + PR automation data source. +--- + +# plural_pr_automation (Data Source) + +PR automation data source. + + + + +## Schema + +### Optional + +- `id` (String) Internal identifier of this PR automation. +- `name` (String) Name of this PR automation. + +### Read-Only + +- `identifier` (String) Identifier of this PR automation. +- `message` (String) Message of this PR automation. +- `title` (String) Title of this PR automation. diff --git a/docs/resources/pr_automation_trigger.md b/docs/resources/pr_automation_trigger.md index 9571118..e9c63dc 100644 --- a/docs/resources/pr_automation_trigger.md +++ b/docs/resources/pr_automation_trigger.md @@ -24,3 +24,4 @@ description: |- - `context` (Map of String) PR Automation configuration context. - `repo_slug` (String) Repo slug of the repository PR Automation should be triggered against. If not provided PR Automation repo will be used. Example format for a github repository: / +- `retrigger_key` (String) Every time this key changes PR automation will be retriggered. diff --git a/docs/resources/stack_run_trigger.md b/docs/resources/stack_run_trigger.md index c1e8a46..db632f3 100644 --- a/docs/resources/stack_run_trigger.md +++ b/docs/resources/stack_run_trigger.md @@ -18,3 +18,7 @@ description: |- ### Required - `id` (String) ID of the Infrastructure Stack that should be used to start a new run from the newest SHA in the stack's run history. + +### Optional + +- `retrigger_key` (String) Every time this key changes stack run will be retriggered. diff --git a/example/prautomation/main.tf b/example/prautomation/main.tf new file mode 100644 index 0000000..e23c470 --- /dev/null +++ b/example/prautomation/main.tf @@ -0,0 +1,24 @@ +terraform { + required_providers { + plural = { + source = "pluralsh/plural" + version = "0.2.1" + } + } +} + +provider "plural" { + use_cli = true +} + +data "plural_pr_automation" "automation" { + name = "pr-test" +} + +# resource "plural_pr_automation_trigger" "trigger" { +# pr_automation_id = data.plural_pr_automation.automation.id +# pr_automation_branch = "prautomation" +# context = { +# version: "v0.0.0" +# } +# } diff --git a/example/prautomationtrigger/main.tf b/example/prautomationtrigger/main.tf deleted file mode 100644 index 53c2920..0000000 --- a/example/prautomationtrigger/main.tf +++ /dev/null @@ -1,20 +0,0 @@ -terraform { - required_providers { - plural = { - source = "pluralsh/plural" - version = "0.2.1" - } - } -} - -provider "plural" { - use_cli = true -} - -resource "plural_pr_automation_trigger" "trigger" { - pr_automation_id = "1cc7483e-78dd-4470-9ae4-6eb2c8cc1785" - pr_automation_branch = "prautomation" - context = { - version: "v0.0.0" - } -} diff --git a/example/stackruntrigger/main.tf b/example/stackruntrigger/main.tf index 40e008f..900f362 100644 --- a/example/stackruntrigger/main.tf +++ b/example/stackruntrigger/main.tf @@ -11,6 +11,11 @@ provider "plural" { use_cli = true } +data "plural_infrastructure_stack" "test" { + name = "test-job" +} + resource "plural_stack_run_trigger" "trigger" { - id = "ecc8966a-edfe-4e48-b5ea-f87c3e97d0a3" + id = data.plural_infrastructure_stack.test.id + retrigger_key = "test" } diff --git a/go.mod b/go.mod index b4691b0..29aeea4 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/mitchellh/go-homedir v1.1.0 - github.com/pluralsh/console/go/client v1.9.0 + github.com/pluralsh/console/go/client v1.10.0 github.com/pluralsh/plural-cli v0.9.14-0.20240730152129-7ce540b144fd github.com/pluralsh/polly v0.1.10 github.com/samber/lo v1.46.0 diff --git a/go.sum b/go.sum index 31eaec1..3b90860 100644 --- a/go.sum +++ b/go.sum @@ -657,8 +657,8 @@ github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFz github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pluralsh/console/go/client v1.9.0 h1:zAXhLUmsYxf1FWNd88N69Glk5A0QMqlSD+mOy9D5+Lo= -github.com/pluralsh/console/go/client v1.9.0/go.mod h1:lpoWASYsM9keNePS3dpFiEisUHEfObIVlSL3tzpKn8k= +github.com/pluralsh/console/go/client v1.10.0 h1:oY8ZeTcoyP5WhrAheQm0PwONJQ/O65sqeWRfgQknMtI= +github.com/pluralsh/console/go/client v1.10.0/go.mod h1:lpoWASYsM9keNePS3dpFiEisUHEfObIVlSL3tzpKn8k= github.com/pluralsh/gqlclient v1.12.1 h1:JDOkP9jjqkPdTYdpH5hooG4F8T6FDH90XfipeXJmJFY= github.com/pluralsh/gqlclient v1.12.1/go.mod h1:OEjN9L63x8m3A3eQBv5kVkFgiY9fp2aZ0cgOF0uII58= github.com/pluralsh/plural-cli v0.9.14-0.20240730152129-7ce540b144fd h1:gg+5AUbiip8WzAQE+avozXLBdP5eS19J6x6+BhtkGNY= diff --git a/internal/datasource/git_repository.go b/internal/datasource/git_repository.go index 94fc692..00d95bd 100644 --- a/internal/datasource/git_repository.go +++ b/internal/datasource/git_repository.go @@ -30,20 +30,20 @@ func (r *GitRepositoryDataSource) Metadata(_ context.Context, req datasource.Met func (r *GitRepositoryDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: "GitRepository resource", + MarkdownDescription: "Git repository data source.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Optional: true, - Description: "Internal identifier of this GitRepository.", - MarkdownDescription: "Internal identifier of this GitRepository.", + Description: "Internal identifier of this Git repository.", + MarkdownDescription: "Internal identifier of this Git repository.", Validators: []validator.String{ stringvalidator.ConflictsWith(path.MatchRoot("url")), }, }, "url": schema.StringAttribute{ Optional: true, - Description: "URL of this GitRepository.", - MarkdownDescription: "URL of this GitRepository.", + Description: "URL of this Git repository.", + MarkdownDescription: "URL of this Git repository.", Validators: []validator.String{ stringvalidator.ConflictsWith(path.MatchRoot("id")), }, @@ -79,7 +79,7 @@ func (r *GitRepositoryDataSource) Read(ctx context.Context, req datasource.ReadR response, err := r.client.GetGitRepository(ctx, data.Id.ValueStringPointer(), data.Url.ValueStringPointer()) if err != nil { - resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get GitRepository, got error: %s", err)) + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get Git repository, got error: %s", err)) return } diff --git a/internal/datasource/infrastructure_stack.go b/internal/datasource/infrastructure_stack.go new file mode 100644 index 0000000..3c07158 --- /dev/null +++ b/internal/datasource/infrastructure_stack.go @@ -0,0 +1,113 @@ +package datasource + +import ( + "context" + "fmt" + + "terraform-provider-plural/internal/client" + "terraform-provider-plural/internal/common" + "terraform-provider-plural/internal/model" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +func NewInfrastructureStackDataSource() datasource.DataSource { + return &InfrastructureStackDataSource{} +} + +// InfrastructureStackDataSource defines the stack data source implementation. +type InfrastructureStackDataSource struct { + client *client.Client +} + +func (r *InfrastructureStackDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_infrastructure_stack" +} + +func (r *InfrastructureStackDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Stack data source.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Optional: true, + Description: "Internal identifier of this stack.", + MarkdownDescription: "Internal identifier of this stack.", + Validators: []validator.String{ + stringvalidator.ExactlyOneOf(path.MatchRoot("name")), + }, + }, + "name": schema.StringAttribute{ + Optional: true, + Description: "Human-readable name of this stack.", + MarkdownDescription: "Human-readable name of this stack.", + Validators: []validator.String{ + stringvalidator.ExactlyOneOf(path.MatchRoot("id")), + }, + }, + "type": schema.StringAttribute{ + Description: "A type for the stack, specifies the tool to use to apply it. ", + MarkdownDescription: "A type for the stack, specifies the tool to use to apply it. ", + Computed: true, + }, + "approval": schema.BoolAttribute{ + Description: "Determines whether to require approval.", + MarkdownDescription: "Determines whether to require approval.", + Computed: true, + }, + "project_id": schema.StringAttribute{ + Description: "ID of the project that this stack belongs to.", + MarkdownDescription: "ID of the project that this stack belongs to.", + Computed: true, + }, + "cluster_id": schema.StringAttribute{ + Description: "The cluster on which the stack is be applied.", + MarkdownDescription: "The cluster on which the stack is be applied.", + Computed: true, + }, + }, + } +} + +func (r *InfrastructureStackDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + data, ok := req.ProviderData.(*common.ProviderData) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Infrastructure Stack Resource Configure Type", + fmt.Sprintf("Expected *common.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + r.client = data.Client +} + +func (r *InfrastructureStackDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + data := new(model.InfrastructureStack) + resp.Diagnostics.Append(req.Config.Get(ctx, data)...) + if resp.Diagnostics.HasError() { + return + } + + response, err := r.client.GetInfrastructureStack(ctx, data.Id.ValueStringPointer(), data.Name.ValueStringPointer()) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get stack, got error: %s", err)) + return + } + + if response == nil || response.InfrastructureStack == nil { + resp.Diagnostics.AddError("Client Error", "Unable to find stack") + return + } + + data.From(response.InfrastructureStack) + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/datasource/pr_automation.go b/internal/datasource/pr_automation.go new file mode 100644 index 0000000..8ef6667 --- /dev/null +++ b/internal/datasource/pr_automation.go @@ -0,0 +1,120 @@ +package datasource + +import ( + "context" + "fmt" + + "terraform-provider-plural/internal/client" + "terraform-provider-plural/internal/common" + "terraform-provider-plural/internal/model" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + console "github.com/pluralsh/console/go/client" +) + +func NewPRAutomationDataSource() datasource.DataSource { + return &PRAutomationDataSource{} +} + +// PRAutomationDataSource defines the PR automation data source implementation. +type PRAutomationDataSource struct { + client *client.Client +} + +func (r *PRAutomationDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_pr_automation" +} + +func (r *PRAutomationDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "PR automation data source.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Optional: true, + Description: "Internal identifier of this PR automation.", + MarkdownDescription: "Internal identifier of this PR automation.", + Validators: []validator.String{ + stringvalidator.ExactlyOneOf(path.MatchRoot("name")), + }, + }, + "name": schema.StringAttribute{ + Optional: true, + Description: "Name of this PR automation.", + MarkdownDescription: "Name of this PR automation.", + Validators: []validator.String{ + stringvalidator.ExactlyOneOf(path.MatchRoot("id")), + }, + }, + "identifier": schema.StringAttribute{ + Computed: true, + Description: "Identifier of this PR automation.", + MarkdownDescription: "Identifier of this PR automation.", + }, + "title": schema.StringAttribute{ + Computed: true, + Description: "Title of this PR automation.", + MarkdownDescription: "Title of this PR automation.", + }, + "message": schema.StringAttribute{ + Computed: true, + Description: "Message of this PR automation.", + MarkdownDescription: "Message of this PR automation.", + }, + }, + } +} + +func (r *PRAutomationDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + data, ok := req.ProviderData.(*common.ProviderData) + if !ok { + resp.Diagnostics.AddError( + "Unexpected PR Automation Resource Configure Type", + fmt.Sprintf("Expected *common.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + r.client = data.Client +} + +func (r *PRAutomationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + data := new(model.PRAutomation) + resp.Diagnostics.Append(req.Config.Get(ctx, data)...) + if resp.Diagnostics.HasError() { + return + } + + var fragment *console.PrAutomationFragment + if !data.Id.IsNull() { + if c, err := r.client.GetPrAutomation(ctx, data.Id.ValueString()); err != nil { + resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Unable to read PR automation by ID, got error: %s", err)) + } else { + fragment = c.PrAutomation + } + } + + if fragment == nil && !data.Name.IsNull() { + if c, err := r.client.GetPrAutomationByName(ctx, data.Name.ValueString()); err != nil { + resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Unable to read PR automation by name, got error: %s", err)) + } else { + fragment = c.PrAutomation + } + } + + if fragment == nil { + resp.Diagnostics.AddError("Client Error", "Unable to read PR automation, see warnings for more information") + return + } + + data.From(fragment) + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/model/infrastructure_stack.go b/internal/model/infrastructure_stack.go index 1b33e8b..27be28a 100644 --- a/internal/model/infrastructure_stack.go +++ b/internal/model/infrastructure_stack.go @@ -15,14 +15,27 @@ import ( ) type InfrastructureStack struct { - Id types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Type types.String `tfsdk:"type"` + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Type types.String `tfsdk:"type"` + Approval types.Bool `tfsdk:"approval"` + ProjectId types.String `tfsdk:"project_id"` + ClusterId types.String `tfsdk:"cluster_id"` +} + +func (is *InfrastructureStack) From(stack *gqlclient.InfrastructureStackFragment) { + is.Id = types.StringPointerValue(stack.ID) + is.Name = types.StringValue(stack.Name) + is.Type = types.StringValue(string(stack.Type)) + is.Approval = types.BoolPointerValue(stack.Approval) + is.ProjectId = common.ProjectFrom(stack.Project) + is.ClusterId = types.StringValue(stack.Cluster.ID) +} + +type InfrastructureStackExtended struct { + InfrastructureStack Actor types.String `tfsdk:"actor"` - Approval types.Bool `tfsdk:"approval"` Detach types.Bool `tfsdk:"detach"` - ProjectId types.String `tfsdk:"project_id"` - ClusterId types.String `tfsdk:"cluster_id"` Repository *InfrastructureStackRepository `tfsdk:"repository"` Configuration *InfrastructureStackConfiguration `tfsdk:"configuration"` Files types.Map `tfsdk:"files"` @@ -31,7 +44,7 @@ type InfrastructureStack struct { Bindings *common.Bindings `tfsdk:"bindings"` } -func (is *InfrastructureStack) Attributes(ctx context.Context, d diag.Diagnostics, client *client.Client) (*gqlclient.StackAttributes, error) { +func (is *InfrastructureStackExtended) Attributes(ctx context.Context, d diag.Diagnostics, client *client.Client) (*gqlclient.StackAttributes, error) { attr := &gqlclient.StackAttributes{ Name: is.Name.ValueString(), Type: gqlclient.StackType(is.Type.ValueString()), @@ -58,7 +71,7 @@ func (is *InfrastructureStack) Attributes(ctx context.Context, d diag.Diagnostic return attr, nil } -func (is *InfrastructureStack) FilesAttributes(ctx context.Context, d diag.Diagnostics) []*gqlclient.StackFileAttributes { +func (is *InfrastructureStackExtended) FilesAttributes(ctx context.Context, d diag.Diagnostics) []*gqlclient.StackFileAttributes { if is.Files.IsNull() { return nil } @@ -74,7 +87,7 @@ func (is *InfrastructureStack) FilesAttributes(ctx context.Context, d diag.Diagn return result } -func (is *InfrastructureStack) EnvironmentAttributes(ctx context.Context, d diag.Diagnostics) []*gqlclient.StackEnvironmentAttributes { +func (is *InfrastructureStackExtended) EnvironmentAttributes(ctx context.Context, d diag.Diagnostics) []*gqlclient.StackEnvironmentAttributes { if is.Environment.IsNull() { return nil } @@ -94,13 +107,8 @@ func (is *InfrastructureStack) EnvironmentAttributes(ctx context.Context, d diag return result } -func (is *InfrastructureStack) From(stack *gqlclient.InfrastructureStackFragment, ctx context.Context, d diag.Diagnostics) { - is.Id = types.StringPointerValue(stack.ID) - is.Name = types.StringValue(stack.Name) - is.Type = types.StringValue(string(stack.Type)) - is.Approval = types.BoolPointerValue(stack.Approval) - is.ProjectId = common.ProjectFrom(stack.Project) - is.ClusterId = types.StringValue(stack.Cluster.ID) +func (is *InfrastructureStackExtended) From(stack *gqlclient.InfrastructureStackFragment, ctx context.Context, d diag.Diagnostics) { + is.InfrastructureStack.From(stack) is.Repository.From(stack.Repository, stack.Git) is.Configuration.From(ctx, stack.Configuration, d) is.Files = infrastructureStackFilesFrom(stack.Files, is.Files, d) diff --git a/internal/model/pr_automation.go b/internal/model/pr_automation.go new file mode 100644 index 0000000..1b0f343 --- /dev/null +++ b/internal/model/pr_automation.go @@ -0,0 +1,22 @@ +package model + +import ( + "github.com/hashicorp/terraform-plugin-framework/types" + gqlclient "github.com/pluralsh/console/go/client" +) + +type PRAutomation struct { + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Identifier types.String `tfsdk:"identifier"` + Title types.String `tfsdk:"title"` + Message types.String `tfsdk:"message"` +} + +func (pra *PRAutomation) From(response *gqlclient.PrAutomationFragment) { + pra.Id = types.StringValue(response.ID) + pra.Name = types.StringValue(response.Name) + pra.Message = types.StringValue(response.Message) + pra.Identifier = types.StringValue(response.Identifier) + pra.Title = types.StringValue(response.Title) +} diff --git a/internal/model/pr_automation_trigger.go b/internal/model/pr_automation_trigger.go index 107a892..d7f74b4 100644 --- a/internal/model/pr_automation_trigger.go +++ b/internal/model/pr_automation_trigger.go @@ -14,6 +14,7 @@ type PrAutomationTrigger struct { RepoSlug types.String `tfsdk:"repo_slug"` PrAutomationBranch types.String `tfsdk:"pr_automation_branch"` Context types.Map `tfsdk:"context"` + RetriggerKey types.String `tfsdk:"retrigger_key"` } func (in *PrAutomationTrigger) ContextJson(ctx context.Context, d diag.Diagnostics) *string { diff --git a/internal/model/stack_run_trigger.go b/internal/model/stack_run_trigger.go index e7abd35..a5cd294 100644 --- a/internal/model/stack_run_trigger.go +++ b/internal/model/stack_run_trigger.go @@ -5,5 +5,6 @@ import ( ) type StackRunTrigger struct { - ID types.String `tfsdk:"id"` + ID types.String `tfsdk:"id"` + RetriggerKey types.String `tfsdk:"retrigger_key"` } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3ecb24b..11ed3db 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -205,6 +205,8 @@ func (p *PluralProvider) DataSources(_ context.Context) []func() datasource.Data ds.NewGroupDataSource, ds.NewUserDataSource, ds.NewConfigDataSource, + ds.NewPRAutomationDataSource, + ds.NewInfrastructureStackDataSource, } } diff --git a/internal/resource/infrastructure_stack.go b/internal/resource/infrastructure_stack.go index 7c0ebd1..ea62ac8 100644 --- a/internal/resource/infrastructure_stack.go +++ b/internal/resource/infrastructure_stack.go @@ -53,7 +53,7 @@ func (r *InfrastructureStackResource) Configure(_ context.Context, req resource. } func (r *InfrastructureStackResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - data := new(model.InfrastructureStack) + data := new(model.InfrastructureStackExtended) resp.Diagnostics.Append(req.Plan.Get(ctx, data)...) if resp.Diagnostics.HasError() { return @@ -75,13 +75,13 @@ func (r *InfrastructureStackResource) Create(ctx context.Context, req resource.C } func (r *InfrastructureStackResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - data := new(model.InfrastructureStack) + data := new(model.InfrastructureStackExtended) resp.Diagnostics.Append(req.State.Get(ctx, data)...) if resp.Diagnostics.HasError() { return } - response, err := r.client.GetInfrastructureStack(ctx, data.Id.ValueString()) + response, err := r.client.GetInfrastructureStack(ctx, data.Id.ValueStringPointer(), nil) if err != nil { resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read infrastructure stack, got error: %s", err)) return @@ -92,7 +92,7 @@ func (r *InfrastructureStackResource) Read(ctx context.Context, req resource.Rea } func (r *InfrastructureStackResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - data := new(model.InfrastructureStack) + data := new(model.InfrastructureStackExtended) resp.Diagnostics.Append(req.Plan.Get(ctx, data)...) if resp.Diagnostics.HasError() { return @@ -113,7 +113,7 @@ func (r *InfrastructureStackResource) Update(ctx context.Context, req resource.U } func (r *InfrastructureStackResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - data := new(model.InfrastructureStack) + data := new(model.InfrastructureStackExtended) resp.Diagnostics.Append(req.State.Get(ctx, data)...) if resp.Diagnostics.HasError() { return @@ -133,7 +133,7 @@ func (r *InfrastructureStackResource) Delete(ctx context.Context, req resource.D } err = wait.PollUntilContextCancel(ctx, 5*time.Second, true, func(ctx context.Context) (bool, error) { - _, err := r.client.GetInfrastructureStack(ctx, data.Id.ValueString()) + _, err := r.client.GetInfrastructureStack(ctx, data.Id.ValueStringPointer(), nil) if client.IsNotFound(err) { return true, nil } diff --git a/internal/resource/pr_automation_trigger.go b/internal/resource/pr_automation_trigger.go index e875c9a..15b914d 100644 --- a/internal/resource/pr_automation_trigger.go +++ b/internal/resource/pr_automation_trigger.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" @@ -59,6 +61,12 @@ func (in *prAutomationTriggerResource) Schema(_ context.Context, _ resource.Sche Optional: true, ElementType: types.StringType, }, + "retrigger_key": schema.StringAttribute{ + Description: "Every time this key changes PR automation will be retriggered.", + MarkdownDescription: "Every time this key changes PR automation will be retriggered.", + Optional: true, + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, }, } } @@ -106,8 +114,29 @@ func (in *prAutomationTriggerResource) Read(_ context.Context, _ resource.ReadRe // Since this is only a trigger, there is no read API. Ignore. } -func (in *prAutomationTriggerResource) Update(_ context.Context, _ resource.UpdateRequest, _ *resource.UpdateResponse) { - // Since this is only a trigger, there is no update API. Ignore. +func (in *prAutomationTriggerResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data, state model.PrAutomationTrigger + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if !data.RetriggerKey.Equal(state.RetriggerKey) || !data.PrAutomationID.Equal(state.PrAutomationID) { + _, err := in.client.CreatePullRequest( + ctx, + data.PrAutomationID.ValueString(), + data.RepoSlug.ValueStringPointer(), + data.PrAutomationBranch.ValueStringPointer(), + data.ContextJson(ctx, resp.Diagnostics), + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create pull request, got error: %s", err)) + return + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } func (in *prAutomationTriggerResource) Delete(_ context.Context, _ resource.DeleteRequest, _ *resource.DeleteResponse) { diff --git a/internal/resource/stack_run_trigger.go b/internal/resource/stack_run_trigger.go index 4f3e517..7dbbdbe 100644 --- a/internal/resource/stack_run_trigger.go +++ b/internal/resource/stack_run_trigger.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "terraform-provider-plural/internal/client" @@ -39,6 +41,12 @@ func (in *stackRunTriggerResource) Schema(_ context.Context, _ resource.SchemaRe stringvalidator.LengthAtLeast(1), }, }, + "retrigger_key": schema.StringAttribute{ + Description: "Every time this key changes stack run will be retriggered.", + MarkdownDescription: "Every time this key changes stack run will be retriggered.", + Optional: true, + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, }, } } @@ -83,8 +91,26 @@ func (in *stackRunTriggerResource) Read(_ context.Context, _ resource.ReadReques // Since this is only a trigger, there is no read API. Ignore. } -func (in *stackRunTriggerResource) Update(_ context.Context, _ resource.UpdateRequest, _ *resource.UpdateResponse) { - // Since this is only a trigger, there is no update API. Ignore. +func (in *stackRunTriggerResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data, state model.StackRunTrigger + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if !data.RetriggerKey.Equal(state.RetriggerKey) || !data.ID.Equal(state.ID) { + _, err := in.client.TriggerRun( + ctx, + data.ID.ValueString(), + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to trigger stack run, got error: %s", err)) + return + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } func (in *stackRunTriggerResource) Delete(_ context.Context, _ resource.DeleteRequest, _ *resource.DeleteResponse) {