func resourceGitlabGroupCreate()

in internal/provider/sdk/resource_gitlab_group.go [378:588]


func resourceGitlabGroupCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
	client := meta.(*gitlab.Client)
	options := &gitlab.CreateGroupOptions{
		Name: gitlab.Ptr(d.Get("name").(string)),
	}

	if v, ok := d.GetOk("path"); ok {
		options.Path = gitlab.Ptr(v.(string))
	}

	if v, ok := d.GetOk("default_branch"); ok {
		options.DefaultBranch = gitlab.Ptr(v.(string))
	}

	if v, ok := d.GetOk("description"); ok {
		options.Description = gitlab.Ptr(v.(string))
	}

	if v, ok := d.GetOk("visibility_level"); ok {
		options.Visibility = stringToVisibilityLevel(v.(string))
	}

	if v, ok := d.GetOk("share_with_group_lock"); ok {
		options.ShareWithGroupLock = gitlab.Ptr(v.(bool))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("lfs_enabled"); ok {
		options.LFSEnabled = gitlab.Ptr(v.(bool))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("request_access_enabled"); ok {
		options.RequestAccessEnabled = gitlab.Ptr(v.(bool))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("require_two_factor_authentication"); ok {
		options.RequireTwoFactorAuth = gitlab.Ptr(v.(bool))
	}

	if v, ok := d.GetOk("two_factor_grace_period"); ok {
		options.TwoFactorGracePeriod = gitlab.Ptr(v.(int))
	}

	if v, ok := d.GetOk("project_creation_level"); ok {
		options.ProjectCreationLevel = stringToProjectCreationLevel(v.(string))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("auto_devops_enabled"); ok {
		options.AutoDevopsEnabled = gitlab.Ptr(v.(bool))
	}

	if v, ok := d.GetOk("subgroup_creation_level"); ok {
		options.SubGroupCreationLevel = stringToSubGroupCreationLevel(v.(string))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("emails_enabled"); ok {
		options.EmailsEnabled = gitlab.Ptr(v.(bool))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("mentions_disabled"); ok {
		options.MentionsDisabled = gitlab.Ptr(v.(bool))
	}

	if v, ok := d.GetOk("parent_id"); ok {
		options.ParentID = gitlab.Ptr(v.(int))
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("default_branch_protection"); ok {
		options.DefaultBranchProtection = gitlab.Ptr(v.(int))
	}

	if v, ok := d.GetOk("default_branch_protection_defaults.0"); ok {
		defaults := v.(map[string]any)
		options.DefaultBranchProtectionDefaults = &gitlab.DefaultBranchProtectionDefaultsOptions{
			AllowedToPush:           gitlab.Ptr(convertAccessLevelNamesToValues(defaults["allowed_to_push"].([]any))),
			AllowForcePush:          gitlab.Ptr(defaults["allow_force_push"].(bool)),
			AllowedToMerge:          gitlab.Ptr(convertAccessLevelNamesToValues(defaults["allowed_to_merge"].([]any))),
			DeveloperCanInitialPush: gitlab.Ptr(defaults["developer_can_initial_push"].(bool)),
		}
	}

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("membership_lock"); ok {
		options.MembershipLock = gitlab.Ptr(v.(bool))
	}

	if v, ok := d.GetOk("extra_shared_runners_minutes_limit"); ok {
		options.ExtraSharedRunnersMinutesLimit = gitlab.Ptr(v.(int))
	}

	if v, ok := d.GetOk("shared_runners_minutes_limit"); ok {
		options.SharedRunnersMinutesLimit = gitlab.Ptr(v.(int))
	}

	avatar, err := handleAvatarOnCreate(d)
	if err != nil {
		return diag.FromErr(err)
	}
	if avatar != nil {
		options.Avatar = &gitlab.GroupAvatar{
			Filename: avatar.Filename,
			Image:    avatar.Image,
		}
	}

	if v, ok := d.GetOk("wiki_access_level"); ok {
		options.WikiAccessLevel = stringToAccessControlValue(v.(string))
	}

	tflog.Debug(ctx, "[DEBUG] create gitlab group", map[string]any{
		"name": *options.Name,
	})

	group, _, err := client.Groups.CreateGroup(options, gitlab.WithContext(ctx))
	if err != nil {
		return diag.FromErr(err)
	}

	// Wait for the Group to return properly before we update it
	// Groups are created asynchronously, so we want to ensure the create operation
	// completely finishes before we act on the group, or we can get an error.
	// see: https://gitlab.com/gitlab-org/terraform-provider-gitlab/-/issues/692
	stateConf := &retry.StateChangeConf{
		Pending: []string{"Creating"},
		Target:  []string{"Created"},
		Refresh: func() (any, string, error) {
			out, _, err := client.Groups.GetGroup(group.ID, nil, gitlab.WithContext(ctx))
			if err != nil {
				if api.Is404(err) {
					return out, "Creating", nil
				}
				tflog.Error(ctx, "[ERROR] Received error retrieving group", map[string]any{
					"group_id": group.ID,
					"error":    err,
				})
				return out, "Error", err
			}
			return out, "Created", nil
		},

		Timeout:    d.Timeout(schema.TimeoutCreate),
		MinTimeout: 3 * time.Second,
		Delay:      5 * time.Second,
	}

	_, err = stateConf.WaitForStateContext(ctx)
	if err != nil {
		return diag.Errorf("error waiting for group (%s) to create: %s", d.Id(), err)
	}

	// Our group has been created, we can now update it.
	d.SetId(fmt.Sprintf("%d", group.ID))

	if _, ok := d.GetOk("push_rules"); ok {
		err := editOrAddGroupPushRules(ctx, client, d.Id(), d)
		if err != nil {
			if api.Is404(err) {
				tflog.Error(ctx, "[ERROR] Failed to edit push rules for group", map[string]any{
					"group_id": d.Id(),
					"error":    err,
				})
				return diag.Errorf("Group push rules are not supported in your version of GitLab")
			}
			return diag.Errorf("Failed to edit push rules for group %q: %s", d.Id(), err)
		}
	}

	var updateOptions gitlab.UpdateGroupOptions

	// nolint:staticcheck // SA1019 ignore deprecated GetOkExists
	// lintignore: XR001 // TODO: replace with alternative for GetOkExists
	if v, ok := d.GetOkExists("prevent_forking_outside_group"); ok {
		updateOptions.PreventForkingOutsideGroup = gitlab.Ptr(v.(bool))
	}

	// IP Restriction can only be set on update.
	if v, ok := d.GetOk("ip_restriction_ranges"); ok {
		updateOptions.IPRestrictionRanges = stringListToCommaSeparatedString(v.([]any))
	}

	// Email domains can only be set on update.
	if v, ok := d.GetOk("allowed_email_domains_list"); ok {
		updateOptions.AllowedEmailDomainsList = stringListToCommaSeparatedString(v.([]any))
	}

	if v, ok := d.GetOk("shared_runners_setting"); ok {
		updateOptions.SharedRunnersSetting = stringToSharedRunnersSetting(v.(string))
	}

	if (updateOptions != gitlab.UpdateGroupOptions{}) {
		if _, _, err = client.Groups.UpdateGroup(d.Id(), &updateOptions, gitlab.WithContext(ctx)); err != nil {
			return diag.Errorf("could not update group after creation %q: %s", d.Id(), err)
		}
	}

	return resourceGitlabGroupRead(ctx, d, meta)
}