func()

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)...)
}