teamcity/global.go (274 lines of code) (raw):

package teamcity import ( "context" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/types" "terraform-provider-teamcity/client" ) var ( _ resource.Resource = &globalResource{} _ resource.ResourceWithConfigure = &globalResource{} _ resource.ResourceWithImportState = &globalResource{} ) func NewGlobalResource() resource.Resource { return &globalResource{} } type globalResource struct { client *client.Client } type globalResourceModel struct { ArtifactDirectories types.String `tfsdk:"artifact_directories"` RootUrl types.String `tfsdk:"root_url"` MaxArtifactSize types.Int64 `tfsdk:"max_artifact_size"` MaxArtifactNumber types.Int64 `tfsdk:"max_artifact_number"` DefaultExecutionTimeout types.Int64 `tfsdk:"default_execution_timeout"` DefaultVCSCheckInterval types.Int64 `tfsdk:"default_vcs_check_interval"` EnforceDefaultVCSCheckInterval types.Bool `tfsdk:"enforce_default_vcs_check_interval"` DefaultQuietPeriod types.Int64 `tfsdk:"default_quiet_period"` Encryption *EncryptionModel `tfsdk:"encryption"` ArtifactIsolation *ArtifactIsolationModel `tfsdk:"artifacts_domain_isolation"` } type EncryptionModel struct { Key types.String `tfsdk:"key"` } type ArtifactIsolationModel struct { Enabled types.Bool `tfsdk:"enabled"` ArtifactsUrl types.String `tfsdk:"artifacts_url"` } func (r *globalResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) { if req.ProviderData == nil { return } r.client = req.ProviderData.(*client.Client) } func (r *globalResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_global_settings" } func (r *globalResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Description: "[General TeamCity configuration](https://www.jetbrains.com/help/teamcity/teamcity-configuration-and-maintenance.html#TeamCity+Configuration)", Attributes: map[string]schema.Attribute{ "artifact_directories": schema.StringAttribute{ Optional: true, Computed: true, Default: stringdefault.StaticString("system/artifacts"), }, "root_url": schema.StringAttribute{ Optional: true, Computed: true, Default: stringdefault.StaticString("http://localhost:8111"), }, "max_artifact_size": schema.Int64Attribute{ Optional: true, Computed: true, Default: int64default.StaticInt64(314572800), }, "max_artifact_number": schema.Int64Attribute{ Optional: true, Computed: true, Default: int64default.StaticInt64(1000), }, "default_execution_timeout": schema.Int64Attribute{ Optional: true, Computed: true, Default: int64default.StaticInt64(0), }, "default_vcs_check_interval": schema.Int64Attribute{ Optional: true, Computed: true, Default: int64default.StaticInt64(60), }, "enforce_default_vcs_check_interval": schema.BoolAttribute{ Optional: true, Computed: true, Default: booldefault.StaticBool(false), }, "default_quiet_period": schema.Int64Attribute{ Optional: true, Computed: true, Default: int64default.StaticInt64(60), }, "encryption": schema.SingleNestedAttribute{ Optional: true, Computed: true, Attributes: map[string]schema.Attribute{ "key": schema.StringAttribute{ Required: true, Sensitive: true, }, }, Default: objectdefault.StaticValue(types.ObjectNull( map[string]attr.Type{"key": types.StringType}, )), }, "artifacts_domain_isolation": schema.SingleNestedAttribute{ Optional: true, Computed: true, Attributes: map[string]schema.Attribute{ "enabled": schema.BoolAttribute{ Optional: true, Computed: true, Default: booldefault.StaticBool(true), Description: "Enabled by default, set false if it needs to be disabled", }, "artifacts_url": schema.StringAttribute{ Optional: true, Computed: true, }, }, Default: objectdefault.StaticValue(types.ObjectValueMust( map[string]attr.Type{ "enabled": types.BoolType, "artifacts_url": types.StringType, }, map[string]attr.Value{ "enabled": types.BoolValue(true), "artifacts_url": types.StringValue(""), }, )), }, }, } } func (r *globalResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { var plan globalResourceModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } newState, err := r.update(plan) if err != nil { resp.Diagnostics.AddError( "Error setting global settings", err.Error(), ) return } if newState.Encryption != nil { newState.Encryption.Key = plan.Encryption.Key } diags = resp.State.Set(ctx, newState) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } } func (r *globalResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { var oldState globalResourceModel diags := req.State.Get(ctx, &oldState) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } result, err := r.client.GetGlobalSettings() if err != nil { resp.Diagnostics.AddError( "Unable to read global settings", err.Error(), ) return } newState, err := r.readState(*result) if err != nil { resp.Diagnostics.AddError( "Unable to read global settings", err.Error(), ) return } if newState.Encryption != nil { newState.Encryption.Key = oldState.Encryption.Key } diags = resp.State.Set(ctx, newState) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } } func (r *globalResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var plan globalResourceModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } newState, err := r.update(plan) if err != nil { resp.Diagnostics.AddError( "Error setting global settings", err.Error(), ) return } if newState.Encryption != nil { newState.Encryption.Key = plan.Encryption.Key } diags = resp.State.Set(ctx, newState) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } } func (r *globalResource) Delete(_ context.Context, _ resource.DeleteRequest, _ *resource.DeleteResponse) { } func (r *globalResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { resp.State.Set(ctx, globalResourceModel{}) } func (r *globalResource) update(plan globalResourceModel) (*globalResourceModel, error) { var key string if plan.Encryption != nil { v := plan.Encryption.Key.ValueString() key = v } enableArtifactsDomainIsolation := true var artifactsURL string if plan.ArtifactIsolation != nil { enableArtifactsDomainIsolation = plan.ArtifactIsolation.Enabled.ValueBool() artifactsURL = plan.ArtifactIsolation.ArtifactsUrl.ValueString() } settings := client.GlobalSettings{ ArtifactDirectories: plan.ArtifactDirectories.ValueString(), RootUrl: plan.RootUrl.ValueString(), MaxArtifactSize: plan.MaxArtifactSize.ValueInt64(), MaxArtifactNumber: plan.MaxArtifactNumber.ValueInt64(), DefaultExecutionTimeout: plan.DefaultExecutionTimeout.ValueInt64(), DefaultVCSCheckInterval: plan.DefaultVCSCheckInterval.ValueInt64(), EnforceDefaultVCSCheckInterval: plan.EnforceDefaultVCSCheckInterval.ValueBool(), DefaultQuietPeriod: plan.DefaultQuietPeriod.ValueInt64(), UseEncryption: plan.Encryption != nil, EncryptionKey: key, ArtifactsDomainIsolation: enableArtifactsDomainIsolation, ArtifactsUrl: artifactsURL, } result, err := r.client.SetGlobalSettings(settings) if err != nil { return nil, err } return r.readState(*result) } func (r *globalResource) readState(result client.GlobalSettings) (*globalResourceModel, error) { var state globalResourceModel state.ArtifactDirectories = types.StringValue(result.ArtifactDirectories) state.RootUrl = types.StringValue(result.RootUrl) state.MaxArtifactSize = types.Int64Value(result.MaxArtifactSize) state.MaxArtifactNumber = types.Int64Value(result.MaxArtifactNumber) state.DefaultExecutionTimeout = types.Int64Value(result.DefaultExecutionTimeout) state.DefaultVCSCheckInterval = types.Int64Value(result.DefaultVCSCheckInterval) state.EnforceDefaultVCSCheckInterval = types.BoolValue(result.EnforceDefaultVCSCheckInterval) state.DefaultQuietPeriod = types.Int64Value(result.DefaultQuietPeriod) if result.UseEncryption { state.Encryption = &EncryptionModel{} } state.ArtifactIsolation = &ArtifactIsolationModel{ Enabled: types.BoolValue(result.ArtifactsDomainIsolation), ArtifactsUrl: types.StringValue(result.ArtifactsUrl), } return &state, nil }