in internal/provider/resource_gitlab_group_protected_environment.go [451:643]
func (r *gitlabGroupProtectedEnvironmentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data *gitlabGroupProtectedEnvironmentResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// local copies of plan arguments
groupID := data.Group.ValueString()
environmentName := data.Environment.ValueString()
// Retrieve the protected environment (to know which deploy/approval rules to remove)
protectedEnvironment, _, err := r.client.GroupProtectedEnvironments.GetGroupProtectedEnvironment(groupID, environmentName, gitlab.WithContext(ctx))
if err != nil {
if api.Is404(err) {
resp.Diagnostics.AddError(
"GitLab Feature not available",
fmt.Sprintf("The protected environment feature is not available on this group. Make sure it's part of an enterprise plan. Error: %s", err.Error()),
)
return
}
resp.Diagnostics.AddError("GitLab API error occured", fmt.Sprintf("Unable to update protected environment details: %s", err.Error()))
return
}
// configure GitLab API call
options := &gitlab.UpdateGroupProtectedEnvironmentOptions{
Name: gitlab.Ptr(environmentName),
}
// deploy access levels
deployAccessLevels := make([]*gitlabGroupProtectedEnvironmentDeployAccessLevelModel, 0, len(data.DeployAccessLevels.Elements()))
resp.Diagnostics.Append(data.DeployAccessLevels.ElementsAs(ctx, &deployAccessLevels, false)...)
if resp.Diagnostics.HasError() {
return
}
deployAccessLevelsOption := make([]*gitlab.UpdateGroupEnvironmentAccessOptions, 0)
for _, v := range deployAccessLevels {
deployAccessLevelOptions := &gitlab.UpdateGroupEnvironmentAccessOptions{}
// the ID will be null when adding a new deploy rule via update
if !v.ID.IsNull() && v.ID.ValueInt64() != 0 {
deployAccessLevelOptions.ID = gitlab.Ptr(int(v.ID.ValueInt64()))
}
if !v.AccessLevel.IsNull() && v.AccessLevel.ValueString() != "" {
deployAccessLevelOptions.AccessLevel = gitlab.Ptr(api.AccessLevelNameToValue[v.AccessLevel.ValueString()])
}
if !v.UserId.IsNull() && v.UserId.ValueInt64() != 0 {
deployAccessLevelOptions.UserID = gitlab.Ptr(int(v.UserId.ValueInt64()))
}
if !v.GroupId.IsNull() && v.GroupId.ValueInt64() != 0 {
deployAccessLevelOptions.GroupID = gitlab.Ptr(int(v.GroupId.ValueInt64()))
}
if !v.GroupInheritanceType.IsNull() && v.GroupInheritanceType.ValueInt64() != 0 {
deployAccessLevelOptions.GroupInheritanceType = gitlab.Ptr(int(v.GroupInheritanceType.ValueInt64()))
}
deployAccessLevelsOption = append(deployAccessLevelsOption, deployAccessLevelOptions)
}
// Remove deploy access levels that aren't present in the config
for _, v := range protectedEnvironment.DeployAccessLevels {
isPresent := false
for _, j := range deployAccessLevels {
if v.ID == int(j.ID.ValueInt64()) {
isPresent = true
break
}
}
// If the existing deploy isn't present, add it to the values to remove it
if !isPresent {
deployAccessLevelOptions := &gitlab.UpdateGroupEnvironmentAccessOptions{
ID: gitlab.Ptr(v.ID),
Destroy: gitlab.Ptr(true),
}
// Seems weird, but the API does validate that these values are present even
// when destroying
if v.AccessLevel != 0 {
deployAccessLevelOptions.AccessLevel = &v.AccessLevel
}
if v.UserID != 0 {
deployAccessLevelOptions.UserID = &v.UserID
}
if v.GroupID != 0 {
deployAccessLevelOptions.GroupID = &v.GroupID
}
deployAccessLevelsOption = append(deployAccessLevelsOption, deployAccessLevelOptions)
}
}
options.DeployAccessLevels = &deployAccessLevelsOption
// approval rules
approvalRules := make([]*gitlabGroupProtectedEnvironmentApprovalRuleModel, 0, len(data.ApprovalRules.Elements()))
resp.Diagnostics.Append(data.ApprovalRules.ElementsAs(ctx, &approvalRules, true)...)
if resp.Diagnostics.HasError() {
return
}
approvalRulesOptionSlice := make([]*gitlab.UpdateGroupEnvironmentApprovalRuleOptions, 0)
for _, v := range approvalRules {
approvalRuleOptions := &gitlab.UpdateGroupEnvironmentApprovalRuleOptions{}
// the ID will be null when adding a new approval rule via update
if !v.ID.IsNull() && v.ID.ValueInt64() != 0 {
approvalRuleOptions.ID = gitlab.Ptr(int(v.ID.ValueInt64()))
}
if !v.AccessLevel.IsNull() && v.AccessLevel.ValueString() != "" {
approvalRuleOptions.AccessLevel = gitlab.Ptr(api.AccessLevelNameToValue[v.AccessLevel.ValueString()])
}
if !v.UserId.IsNull() && v.UserId.ValueInt64() != 0 {
approvalRuleOptions.UserID = gitlab.Ptr(int(v.UserId.ValueInt64()))
}
if !v.GroupId.IsNull() && v.GroupId.ValueInt64() != 0 {
approvalRuleOptions.GroupID = gitlab.Ptr(int(v.GroupId.ValueInt64()))
}
if !v.GroupInheritanceType.IsNull() && v.GroupInheritanceType.ValueInt64() != 0 {
approvalRuleOptions.GroupInheritanceType = gitlab.Ptr(int(v.GroupInheritanceType.ValueInt64()))
}
if !v.RequiredApprovals.IsNull() && v.RequiredApprovals.ValueInt64() != 0 {
approvalRuleOptions.RequiredApprovalCount = gitlab.Ptr(int(v.RequiredApprovals.ValueInt64()))
}
approvalRulesOptionSlice = append(approvalRulesOptionSlice, approvalRuleOptions)
}
// Remove approval levels that aren't present in the config
for _, v := range protectedEnvironment.ApprovalRules {
isPresent := false
for _, j := range approvalRules {
if v.ID == int(j.ID.ValueInt64()) {
isPresent = true
break
}
}
// If the existing deploy isn't present, add it to the values to remove it
if !isPresent {
approvalRuleOptions := &gitlab.UpdateGroupEnvironmentApprovalRuleOptions{
ID: gitlab.Ptr(v.ID),
Destroy: gitlab.Ptr(true),
}
// Seems weird, but the API does validate that these values are present even
// when destroying
if v.AccessLevel != 0 {
approvalRuleOptions.AccessLevel = &v.AccessLevel
}
if v.UserID != 0 {
approvalRuleOptions.UserID = &v.UserID
}
if v.GroupID != 0 {
approvalRuleOptions.GroupID = &v.GroupID
}
approvalRulesOptionSlice = append(approvalRulesOptionSlice, approvalRuleOptions)
}
}
options.ApprovalRules = &approvalRulesOptionSlice
tflog.Debug(ctx, "Updating group protected environment with options", map[string]any{
"group": groupID,
"options": options,
"environment_name": environmentName,
})
protectedEnvironment, _, err = r.client.GroupProtectedEnvironments.UpdateGroupProtectedEnvironment(groupID, environmentName, options, gitlab.WithContext(ctx))
if err != nil {
if api.Is404(err) {
resp.Diagnostics.AddError(
"GitLab Feature not available",
fmt.Sprintf("The protected environment feature is not available on this group. Make sure it's part of an enterprise plan. Error: %s", err.Error()),
)
return
}
resp.Diagnostics.AddError("GitLab API error occured", fmt.Sprintf("Unable to update protected environment details: %s", err.Error()))
return
}
tflog.Debug(ctx, "Updating group protected environment completed with options", map[string]any{
"group": groupID,
"environment_name": environmentName,
"result": protectedEnvironment,
})
// Add data to state
r.protectedEnvironmentToStateModel(ctx, resp.Diagnostics, groupID, protectedEnvironment, data)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}