teamcity/vcsroot.go (696 lines of code) (raw):
package teamcity
import (
"context"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"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/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"strconv"
"terraform-provider-teamcity/client"
"terraform-provider-teamcity/models"
)
var (
_ resource.Resource = &vcsRootResource{}
_ resource.ResourceWithConfigure = &vcsRootResource{}
_ resource.ResourceWithImportState = &vcsRootResource{}
)
func NewVcsRootResource() resource.Resource {
return &vcsRootResource{}
}
type vcsRootResource struct {
client *client.Client
}
type vcsRootResourceModel struct {
Name types.String `tfsdk:"name"`
Id types.String `tfsdk:"id"`
ProjectId types.String `tfsdk:"project_id"`
PollingInterval types.Int64 `tfsdk:"polling_interval"`
Git *GitPropertiesModel `tfsdk:"git"`
}
type GitPropertiesModel struct {
Url types.String `tfsdk:"url" teamcity:"url"`
PushUrl types.String `tfsdk:"push_url"`
Branch types.String `tfsdk:"branch" teamcity:"branch"`
BranchSpec types.String `tfsdk:"branch_spec"`
TagsAsBranches types.Bool `tfsdk:"tags_as_branches"`
UsernameStyle types.String `tfsdk:"username_style"`
Submodules types.String `tfsdk:"submodules"`
UsernameForTags types.String `tfsdk:"username_for_tags"`
AuthMethod types.String `tfsdk:"auth_method"`
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
UploadedKey types.String `tfsdk:"uploaded_key"`
PrivateKeyPath types.String `tfsdk:"private_key_path"`
Passphrase types.String `tfsdk:"passphrase"`
IgnoreKnownHosts types.Bool `tfsdk:"ignore_known_hosts"`
ConvertCrlf types.Bool `tfsdk:"convert_crlf"`
PathToGit types.String `tfsdk:"path_to_git"`
CheckoutPolicy types.String `tfsdk:"checkout_policy"`
CleanPolicy types.String `tfsdk:"clean_policy"`
CleanFilesPolicy types.String `tfsdk:"clean_files_policy"`
TokenId types.String `tfsdk:"token_id"`
}
func (r *vcsRootResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_vcsroot"
}
func (r *vcsRootResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "A VCS root in TeamCity defines a connection to a version control system. More info [here](https://www.jetbrains.com/help/teamcity/vcs-root.html)",
Attributes: map[string]schema.Attribute{
"name": schema.StringAttribute{
Required: true,
},
"id": schema.StringAttribute{
Optional: true,
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"project_id": schema.StringAttribute{
Required: true,
},
"polling_interval": schema.Int64Attribute{
Optional: true,
},
"git": schema.SingleNestedAttribute{
Required: true,
Attributes: map[string]schema.Attribute{
"url": schema.StringAttribute{
Required: true,
},
"push_url": schema.StringAttribute{
Optional: true,
},
"branch": schema.StringAttribute{
Required: true,
},
"branch_spec": schema.StringAttribute{
Optional: true,
},
"tags_as_branches": schema.BoolAttribute{
Optional: true,
},
"username_style": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
//TODO other syntax?
stringvalidator.OneOf([]string{"USERID", "NAME", "EMAIL", "FULL"}...),
},
Default: stringdefault.StaticString("USERID"),
},
"submodules": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
//TODO other syntax?
stringvalidator.OneOf([]string{"IGNORE", "CHECKOUT"}...),
},
Default: stringdefault.StaticString("CHECKOUT"),
},
"username_for_tags": schema.StringAttribute{
Optional: true,
},
"auth_method": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
stringvalidator.OneOf([]string{
//TODO other syntax? alternate nested types
"ANONYMOUS",
"PASSWORD",
"TEAMCITY_SSH_KEY",
"ACCESS_TOKEN",
"PRIVATE_KEY_DEFAULT",
"PRIVATE_KEY_FILE",
}...),
},
},
"username": schema.StringAttribute{
Optional: true,
},
"password": schema.StringAttribute{
Optional: true,
Sensitive: true,
},
"uploaded_key": schema.StringAttribute{
Optional: true,
},
"private_key_path": schema.StringAttribute{
Optional: true,
},
"passphrase": schema.StringAttribute{
Optional: true,
Sensitive: true,
},
"ignore_known_hosts": schema.BoolAttribute{
Optional: true,
Computed: true,
Default: booldefault.StaticBool(true),
},
"convert_crlf": schema.BoolAttribute{
Optional: true,
},
"path_to_git": schema.StringAttribute{
Optional: true,
},
"checkout_policy": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.OneOf([]string{"AUTO", "USE_MIRRORS", "NO_MIRRORS", "SHALLOW_CLONE"}...),
},
Default: stringdefault.StaticString("AUTO"),
},
"clean_policy": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.OneOf([]string{"ON_BRANCH_CHANGE", "ALWAYS", "NEVER"}...),
},
Default: stringdefault.StaticString("ON_BRANCH_CHANGE"),
},
"clean_files_policy": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.OneOf([]string{"ALL_UNTRACKED", "IGNORED_ONLY", "NON_IGNORED_ONLY"}...),
},
Default: stringdefault.StaticString("ALL_UNTRACKED"),
},
"token_id": schema.StringAttribute{
Optional: true,
},
},
},
},
}
}
func (r *vcsRootResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
if req.ProviderData == nil {
return
}
r.client = req.ProviderData.(*client.Client)
}
func (r *vcsRootResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var plan vcsRootResourceModel
diags := req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
var id *string
if plan.Id.IsUnknown() {
id = nil
} else {
val := plan.Id.ValueString()
id = &val
}
root := client.VcsRoot{
Name: plan.Name.ValueString(),
Id: id,
VcsName: "jetbrains.git",
Project: client.ProjectLocator{
Id: plan.ProjectId.ValueString(),
},
}
props := []models.Property{
{Name: "url", Value: plan.Git.Url.ValueString()},
{Name: "branch", Value: plan.Git.Branch.ValueString()},
}
if plan.Git.PushUrl.IsNull() != true {
props = append(props, models.Property{Name: "push_url", Value: plan.Git.PushUrl.ValueString()})
}
if plan.Git.BranchSpec.IsNull() != true {
props = append(props, models.Property{Name: "teamcity:branchSpec", Value: plan.Git.BranchSpec.ValueString()})
}
if plan.Git.TagsAsBranches.IsNull() != true {
val := strconv.FormatBool(plan.Git.TagsAsBranches.ValueBool())
props = append(props, models.Property{Name: "reportTagRevisions", Value: val})
}
if plan.Git.UsernameStyle.IsNull() != true {
props = append(props, models.Property{Name: "usernameStyle", Value: plan.Git.UsernameStyle.ValueString()})
}
if plan.Git.Submodules.IsNull() != true {
props = append(props, models.Property{Name: "submoduleCheckout", Value: plan.Git.Submodules.ValueString()})
}
if plan.Git.UsernameForTags.IsNull() != true {
props = append(props, models.Property{Name: "userForTags", Value: plan.Git.UsernameForTags.ValueString()})
}
if plan.Git.AuthMethod.IsNull() != true {
props = append(props, models.Property{Name: "authMethod", Value: plan.Git.AuthMethod.ValueString()})
}
if plan.Git.Username.IsNull() != true {
props = append(props, models.Property{Name: "username", Value: plan.Git.Username.ValueString()})
}
if plan.Git.Password.IsNull() != true {
props = append(props, models.Property{Name: "secure:password", Value: plan.Git.Password.ValueString()})
}
if plan.Git.UploadedKey.IsNull() != true {
props = append(props, models.Property{Name: "teamcitySshKey", Value: plan.Git.UploadedKey.ValueString()})
}
if plan.Git.PrivateKeyPath.IsNull() != true {
props = append(props, models.Property{Name: "privateKeyPath", Value: plan.Git.PrivateKeyPath.ValueString()})
}
if plan.Git.Passphrase.IsNull() != true {
props = append(props, models.Property{Name: "secure:passphrase", Value: plan.Git.Passphrase.ValueString()})
}
if plan.Git.IgnoreKnownHosts.IsNull() != true {
val := strconv.FormatBool(plan.Git.IgnoreKnownHosts.ValueBool())
props = append(props, models.Property{Name: "ignoreKnownHosts", Value: val})
}
if plan.Git.ConvertCrlf.IsNull() != true {
val := strconv.FormatBool(plan.Git.ConvertCrlf.ValueBool())
props = append(props, models.Property{Name: "serverSideAutoCrlf", Value: val})
}
if plan.Git.PathToGit.IsNull() != true {
props = append(props, models.Property{Name: "agentGitPath", Value: plan.Git.PathToGit.ValueString()})
}
if plan.Git.CheckoutPolicy.IsNull() != true {
props = append(props, models.Property{Name: "useAlternates", Value: plan.Git.CheckoutPolicy.ValueString()})
}
if plan.Git.CleanPolicy.IsNull() != true {
props = append(props, models.Property{Name: "agentCleanPolicy", Value: plan.Git.CleanPolicy.ValueString()})
}
if plan.Git.CleanFilesPolicy.IsNull() != true {
props = append(props, models.Property{Name: "agentCleanFilesPolicy", Value: plan.Git.CleanFilesPolicy.ValueString()})
}
if plan.Git.TokenId.IsNull() != true {
props = append(props, models.Property{Name: "tokenId", Value: plan.Git.TokenId.ValueString()})
}
root.Properties = models.Properties{
Property: props,
}
if plan.PollingInterval.IsNull() != true {
val := int(plan.PollingInterval.ValueInt64())
root.PollingInterval = &val
}
actual, err := r.client.NewVcsRoot(root)
if err != nil {
resp.Diagnostics.AddError(
"Error setting VCS root",
err.Error(),
)
return
}
newState, err := r.readState(actual)
if err != nil {
resp.Diagnostics.AddError(
"REST returned invalid value: ",
err.Error(),
)
return
}
newState.Git.Password = plan.Git.Password
newState.Git.Passphrase = plan.Git.Passphrase
diags = resp.State.Set(ctx, newState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
func (r *vcsRootResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var oldState vcsRootResourceModel
diags := req.State.Get(ctx, &oldState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
actual, err := r.client.GetVcsRoot(oldState.Id.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Error Reading VCS root",
err.Error(),
)
return
}
if actual == nil {
resp.State.RemoveResource(ctx)
return
}
newState, err := r.readState(*actual)
if err != nil {
resp.Diagnostics.AddError(
"REST returned invalid value: ",
err.Error(),
)
return
}
if oldState.Git != nil {
newState.Git.Password = oldState.Git.Password
newState.Git.Passphrase = oldState.Git.Passphrase
}
diags = resp.State.Set(ctx, newState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
func (r *vcsRootResource) readState(result client.VcsRoot) (vcsRootResourceModel, error) {
var state vcsRootResourceModel
state.Name = types.StringValue(result.Name)
state.Id = types.StringValue(*result.Id)
state.ProjectId = types.StringValue(result.Project.Id)
if result.PollingInterval != nil {
state.PollingInterval = types.Int64Value(int64(*result.PollingInterval))
}
props := make(map[string]string)
for _, p := range result.Properties.Property {
props[p.Name] = p.Value
}
state.Git = &GitPropertiesModel{
Url: types.StringValue(props["url"]),
Branch: types.StringValue(props["branch"]),
}
if val, ok := props["push_url"]; ok {
state.Git.PushUrl = types.StringValue(val)
}
if val, ok := props["teamcity:branchSpec"]; ok {
state.Git.BranchSpec = types.StringValue(val)
}
if val, ok := props["reportTagRevisions"]; ok {
v, err := strconv.ParseBool(val)
if err != nil {
return vcsRootResourceModel{}, err
}
state.Git.TagsAsBranches = types.BoolValue(v)
}
if val, ok := props["usernameStyle"]; ok {
state.Git.UsernameStyle = types.StringValue(val)
}
if val, ok := props["submoduleCheckout"]; ok {
state.Git.Submodules = types.StringValue(val)
}
if val, ok := props["userForTags"]; ok {
state.Git.UsernameForTags = types.StringValue(val)
}
if val, ok := props["authMethod"]; ok {
state.Git.AuthMethod = types.StringValue(val)
}
if val, ok := props["username"]; ok {
state.Git.Username = types.StringValue(val)
}
if val, ok := props["teamcitySshKey"]; ok {
state.Git.UploadedKey = types.StringValue(val)
}
if val, ok := props["privateKeyPath"]; ok {
state.Git.PrivateKeyPath = types.StringValue(val)
}
if val, ok := props["ignoreKnownHosts"]; ok {
v, err := strconv.ParseBool(val)
if err != nil {
return vcsRootResourceModel{}, err
}
state.Git.IgnoreKnownHosts = types.BoolValue(v)
}
if val, ok := props["serverSideAutoCrlf"]; ok {
v, err := strconv.ParseBool(val)
if err != nil {
return vcsRootResourceModel{}, err
}
state.Git.ConvertCrlf = types.BoolValue(v)
}
if val, ok := props["agentGitPath"]; ok {
state.Git.PathToGit = types.StringValue(val)
}
if val, ok := props["useAlternates"]; ok {
state.Git.CheckoutPolicy = types.StringValue(val)
}
if val, ok := props["agentCleanPolicy"]; ok {
state.Git.CleanPolicy = types.StringValue(val)
}
if val, ok := props["agentCleanFilesPolicy"]; ok {
state.Git.CleanFilesPolicy = types.StringValue(val)
}
if val, ok := props["tokenId"]; ok {
state.Git.TokenId = types.StringValue(val)
}
return state, nil
}
func (r *vcsRootResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var plan vcsRootResourceModel
diags := req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
var oldState vcsRootResourceModel
diags = req.State.Get(ctx, &oldState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
var newState vcsRootResourceModel
newState.Git = &GitPropertiesModel{}
resourceId := oldState.Id.ValueString()
if result, ok := r.setFieldString(resourceId, "name", oldState.Name, plan.Name, &resp.Diagnostics); ok {
newState.Name = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "project", oldState.ProjectId, plan.ProjectId, &resp.Diagnostics); ok {
newState.ProjectId = result
} else {
return
}
if result, ok := r.setFieldInt(resourceId, "modificationCheckInterval", oldState.PollingInterval, plan.PollingInterval, &resp.Diagnostics); ok {
newState.PollingInterval = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/url", oldState.Git.Url, plan.Git.Url, &resp.Diagnostics); ok {
newState.Git.Url = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/push_url", oldState.Git.PushUrl, plan.Git.PushUrl, &resp.Diagnostics); ok {
newState.Git.PushUrl = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/branch", oldState.Git.Branch, plan.Git.Branch, &resp.Diagnostics); ok {
newState.Git.Branch = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/teamcity:branchSpec", oldState.Git.BranchSpec, plan.Git.BranchSpec, &resp.Diagnostics); ok {
newState.Git.BranchSpec = result
} else {
return
}
if result, ok := r.setFieldBool(resourceId, "properties/reportTagRevisions", oldState.Git.TagsAsBranches, plan.Git.TagsAsBranches, &resp.Diagnostics); ok {
newState.Git.TagsAsBranches = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/usernameStyle", oldState.Git.UsernameStyle, plan.Git.UsernameStyle, &resp.Diagnostics); ok {
newState.Git.UsernameStyle = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/submoduleCheckout", oldState.Git.Submodules, plan.Git.Submodules, &resp.Diagnostics); ok {
newState.Git.Submodules = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/userForTags", oldState.Git.UsernameForTags, plan.Git.UsernameForTags, &resp.Diagnostics); ok {
newState.Git.UsernameForTags = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/authMethod", oldState.Git.AuthMethod, plan.Git.AuthMethod, &resp.Diagnostics); ok {
newState.Git.AuthMethod = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/username", oldState.Git.Username, plan.Git.Username, &resp.Diagnostics); ok {
newState.Git.Username = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/secure:password", oldState.Git.Password, plan.Git.Password, &resp.Diagnostics); ok {
newState.Git.Password = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/teamcitySshKey", oldState.Git.UploadedKey, plan.Git.UploadedKey, &resp.Diagnostics); ok {
newState.Git.UploadedKey = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/privateKeyPath", oldState.Git.PrivateKeyPath, plan.Git.PrivateKeyPath, &resp.Diagnostics); ok {
newState.Git.PrivateKeyPath = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/secure:passphrase", oldState.Git.Passphrase, plan.Git.Passphrase, &resp.Diagnostics); ok {
newState.Git.Passphrase = result
} else {
return
}
if result, ok := r.setFieldBool(resourceId, "properties/ignoreKnownHosts", oldState.Git.IgnoreKnownHosts, plan.Git.IgnoreKnownHosts, &resp.Diagnostics); ok {
newState.Git.IgnoreKnownHosts = result
} else {
return
}
if result, ok := r.setFieldBool(resourceId, "properties/serverSideAutoCrlf", oldState.Git.ConvertCrlf, plan.Git.ConvertCrlf, &resp.Diagnostics); ok {
newState.Git.ConvertCrlf = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/agentGitPath", oldState.Git.PathToGit, plan.Git.PathToGit, &resp.Diagnostics); ok {
newState.Git.PathToGit = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/useAlternates", oldState.Git.CheckoutPolicy, plan.Git.CheckoutPolicy, &resp.Diagnostics); ok {
newState.Git.CheckoutPolicy = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/agentCleanPolicy", oldState.Git.CleanPolicy, plan.Git.CleanPolicy, &resp.Diagnostics); ok {
newState.Git.CleanPolicy = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/agentCleanFilesPolicy", oldState.Git.CleanFilesPolicy, plan.Git.CleanFilesPolicy, &resp.Diagnostics); ok {
newState.Git.CleanFilesPolicy = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "properties/tokenId", oldState.Git.TokenId, plan.Git.TokenId, &resp.Diagnostics); ok {
newState.Git.TokenId = result
} else {
return
}
if result, ok := r.setFieldString(resourceId, "id", oldState.Id, plan.Id, &resp.Diagnostics); ok {
newState.Id = result
} else {
return
}
diags = resp.State.Set(ctx, newState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
func (r *vcsRootResource) setFieldString(id, name string, state, plan types.String, diag *diag.Diagnostics) (types.String, bool) {
if plan.Equal(state) {
return state, true
}
var strVal *string
if plan.IsNull() {
strVal = nil
} else {
val := plan.ValueString()
strVal = &val
}
result, err := r.client.SetField("vcs-roots", id, name, strVal)
if err != nil {
diag.AddError(
"Error setting VCS root field",
err.Error(),
)
return types.String{}, false
}
if result == "" {
return types.StringNull(), true
}
return types.StringValue(result), true
}
func (r *vcsRootResource) setFieldInt(id, name string, state, plan types.Int64, diag *diag.Diagnostics) (types.Int64, bool) {
if plan.Equal(state) {
return state, true
}
var strVal *string
if plan.IsNull() {
// modificationCheckInterval is the only usage for now,
// and it doesn't support DELETE method
val := ""
strVal = &val
} else {
val := strconv.FormatInt(plan.ValueInt64(), 10)
strVal = &val
}
result, err := r.client.SetField("vcs-roots", id, name, strVal)
if err != nil {
diag.AddError(
"Error setting VCS root field",
err.Error(),
)
return types.Int64{}, false
}
if result == "" {
return types.Int64Null(), true
}
intVal, err := strconv.ParseInt(result, 10, 64)
if err != nil {
diag.AddError(
"Error setting VCS root field",
err.Error(),
)
return types.Int64{}, false
}
return types.Int64Value(intVal), true
}
func (r *vcsRootResource) setFieldBool(id, name string, state, plan types.Bool, diag *diag.Diagnostics) (types.Bool, bool) {
if plan.Equal(state) {
return state, true
}
var strVal *string
if plan.IsNull() {
strVal = nil
} else {
val := strconv.FormatBool(plan.ValueBool())
strVal = &val
}
result, err := r.client.SetField("vcs-roots", id, name, strVal)
if err != nil {
diag.AddError(
"Error setting VCS root field",
err.Error(),
)
return types.Bool{}, false
}
if result == "" {
return types.BoolNull(), true
}
val, err := strconv.ParseBool(result)
if err != nil {
diag.AddError(
"Error setting VCS root field",
err.Error(),
)
return types.Bool{}, false
}
return types.BoolValue(val), true
}
func (r *vcsRootResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var state vcsRootResourceModel
diags := req.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
err := r.client.DetachVcsRoot(state.Id.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Error detaching VCS root from build configurations",
err.Error(),
)
return
}
err = r.client.DeleteVcsRoot(state.Id.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Error Deleting VCS root",
err.Error(),
)
return
}
}
func (r *vcsRootResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}