From b7d1f14b0e7e65a7f3bbfa92b0650c824286c04b Mon Sep 17 00:00:00 2001 From: Waseem Hassan Date: Thu, 18 Oct 2018 13:02:59 +0500 Subject: [PATCH 01/29] Add support for branch protection --- ...source_gitlab_project_branch_protection.go | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 gitlab/resource_gitlab_project_branch_protection.go diff --git a/gitlab/resource_gitlab_project_branch_protection.go b/gitlab/resource_gitlab_project_branch_protection.go new file mode 100644 index 000000000..2949880c3 --- /dev/null +++ b/gitlab/resource_gitlab_project_branch_protection.go @@ -0,0 +1,118 @@ +package gitlab + +import ( + "log" + + "github.com/hashicorp/terraform/helper/schema" + gitlab "github.com/xanzy/go-gitlab" +) + +func resourceGitlabProjectBranchProtection() *schema.Resource { + acceptedAccessLevels := []string{ + "master", + "developer", + } + return &schema.Resource{ + Create: resourceGitlabProjectBranchProtectionCreate, + Read: resourceGitlabProjectBranchProtectionRead, + Delete: resourceGitlabProjectBranchProtectionDelete, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "branch": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "merge_access_level": { + Type: schema.TypeString, + ValidateFunc: validateValueFunc(acceptedAccessLevels), + Required: true, + ForceNew: true, + }, + "push_access_level": { + Type: schema.TypeString, + ValidateFunc: validateValueFunc(acceptedAccessLevels), + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceGitlabProjectBranchProtectionCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + mergeAccessLevel := accessLevelID[d.Get("merge_access_level").(string)] + pushAccessLevel := accessLevelID[d.Get("push_access_level").(string)] + + options := &gitlab.ProtectRepositoryBranchesOptions{ + Name: gitlab.String(d.Get("branch").(string)), + MergeAccessLevel: &mergeAccessLevel, + PushAccessLevel: &pushAccessLevel, + } + + log.Printf("[DEBUG] create gitlab project branch protection on %q", options.Name) + + bp, _, err := client.ProtectedBranches.ProtectRepositoryBranches(project, options) + if err != nil { + return err + } + + d.SetId(buildTwoPartID(&project, &bp.Name)) + + return resourceGitlabProjectBranchProtectionRead(d, meta) +} + +func resourceGitlabProjectBranchProtectionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project, branch, err := projectAndBranchFromID(d.Id()) + if err != nil { + return err + } + + log.Printf("[DEBUG] read gitlab branch protection for project %s, branch %s", project, branch) + + pb, response, err := client.ProtectedBranches.GetProtectedBranch(project, branch) + if err != nil { + if response.StatusCode == 404 { + log.Printf("[WARN] removing project branch protection %s from state because it no longer exists in gitlab", branch) + d.SetId("") + return nil + } + + return err + } + + d.Set("project", project) + d.Set("branch", pb.Name) + d.Set("merge_access_level", pb.MergeAccessLevels[0].AccessLevel) + d.Set("push_access_level", pb.PushAccessLevels[0].AccessLevel) + + d.SetId(buildTwoPartID(&project, &pb.Name)) + + return nil +} + +func resourceGitlabProjectBranchProtectionDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + branch := d.Get("branch").(string) + + log.Printf("[DEBUG] Delete gitlab protected branch %s for project %s", branch, project) + + _, err := client.ProtectedBranches.UnprotectRepositoryBranches(project, branch) + return err +} + +func projectAndBranchFromID(id string) (string, string, error) { + project, branch, err := parseTwoPartID(id) + + if err != nil { + log.Printf("[WARN] cannot get group member id from input: %v", id) + } + return project, branch, err +} From d9f1e4f2cde078e21e2b0f4938c3b2e682c9b0e7 Mon Sep 17 00:00:00 2001 From: Waseem Hassan Date: Thu, 18 Oct 2018 13:04:09 +0500 Subject: [PATCH 02/29] Add gitlab_project_branch_protection to provider --- gitlab/provider.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/gitlab/provider.go b/gitlab/provider.go index f3081e54b..acbe3b05f 100644 --- a/gitlab/provider.go +++ b/gitlab/provider.go @@ -47,16 +47,17 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "gitlab_group": resourceGitlabGroup(), - "gitlab_project": resourceGitlabProject(), - "gitlab_label": resourceGitlabLabel(), - "gitlab_project_hook": resourceGitlabProjectHook(), - "gitlab_deploy_key": resourceGitlabDeployKey(), - "gitlab_user": resourceGitlabUser(), - "gitlab_project_membership": resourceGitlabProjectMembership(), - "gitlab_group_membership": resourceGitlabGroupMembership(), - "gitlab_project_variable": resourceGitlabProjectVariable(), - "gitlab_group_variable": resourceGitlabGroupVariable(), + "gitlab_group": resourceGitlabGroup(), + "gitlab_project": resourceGitlabProject(), + "gitlab_label": resourceGitlabLabel(), + "gitlab_project_hook": resourceGitlabProjectHook(), + "gitlab_project_branch_protection": resourceGitlabProjectBranchProtection(), + "gitlab_deploy_key": resourceGitlabDeployKey(), + "gitlab_user": resourceGitlabUser(), + "gitlab_project_membership": resourceGitlabProjectMembership(), + "gitlab_group_membership": resourceGitlabGroupMembership(), + "gitlab_project_variable": resourceGitlabProjectVariable(), + "gitlab_group_variable": resourceGitlabGroupVariable(), }, ConfigureFunc: providerConfigure, From 8da2712eda93bd0ceeebbcc693ffccd5a7444279 Mon Sep 17 00:00:00 2001 From: Waseem Hassan Date: Thu, 18 Oct 2018 15:00:59 +0500 Subject: [PATCH 03/29] Update resource name --- gitlab/provider.go | 1 + gitlab/resource_gitlab_branch_protection.go | 118 ++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 gitlab/resource_gitlab_branch_protection.go diff --git a/gitlab/provider.go b/gitlab/provider.go index f3081e54b..4e03150be 100644 --- a/gitlab/provider.go +++ b/gitlab/provider.go @@ -47,6 +47,7 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ + "gitlab_branch_protection": resourceGitlabBranchProtection(), "gitlab_group": resourceGitlabGroup(), "gitlab_project": resourceGitlabProject(), "gitlab_label": resourceGitlabLabel(), diff --git a/gitlab/resource_gitlab_branch_protection.go b/gitlab/resource_gitlab_branch_protection.go new file mode 100644 index 000000000..06943de9c --- /dev/null +++ b/gitlab/resource_gitlab_branch_protection.go @@ -0,0 +1,118 @@ +package gitlab + +import ( + "log" + + "github.com/hashicorp/terraform/helper/schema" + gitlab "github.com/xanzy/go-gitlab" +) + +func resourceGitlabBranchProtection() *schema.Resource { + acceptedAccessLevels := []string{ + "master", + "developer", + } + return &schema.Resource{ + Create: resourceGitlabBranchProtectionCreate, + Read: resourceGitlabBranchProtectionRead, + Delete: resourceGitlabBranchProtectionDelete, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "branch": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "merge_access_level": { + Type: schema.TypeString, + ValidateFunc: validateValueFunc(acceptedAccessLevels), + Required: true, + ForceNew: true, + }, + "push_access_level": { + Type: schema.TypeString, + ValidateFunc: validateValueFunc(acceptedAccessLevels), + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceGitlabBranchProtectionCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + mergeAccessLevel := accessLevelID[d.Get("merge_access_level").(string)] + pushAccessLevel := accessLevelID[d.Get("push_access_level").(string)] + + options := &gitlab.ProtectRepositoryBranchesOptions{ + Name: gitlab.String(d.Get("branch").(string)), + MergeAccessLevel: &mergeAccessLevel, + PushAccessLevel: &pushAccessLevel, + } + + log.Printf("[DEBUG] create gitlab branch protection on %s for project %s", options.Name, project) + + bp, _, err := client.ProtectedBranches.ProtectRepositoryBranches(project, options) + if err != nil { + return err + } + + d.SetId(buildTwoPartID(&project, &bp.Name)) + + return resourceGitlabBranchProtectionRead(d, meta) +} + +func resourceGitlabBranchProtectionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project, branch, err := projectAndBranchFromID(d.Id()) + if err != nil { + return err + } + + log.Printf("[DEBUG] read gitlab branch protection for project %s, branch %s", project, branch) + + pb, response, err := client.ProtectedBranches.GetProtectedBranch(project, branch) + if err != nil { + if response.StatusCode == 404 { + log.Printf("[WARN] removing project branch protection %s from state because it no longer exists in gitlab", branch) + d.SetId("") + return nil + } + + return err + } + + d.Set("project", project) + d.Set("branch", pb.Name) + d.Set("merge_access_level", pb.MergeAccessLevels[0].AccessLevel) + d.Set("push_access_level", pb.PushAccessLevels[0].AccessLevel) + + d.SetId(buildTwoPartID(&project, &pb.Name)) + + return nil +} + +func resourceGitlabBranchProtectionDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + branch := d.Get("branch").(string) + + log.Printf("[DEBUG] Delete gitlab protected branch %s for project %s", branch, project) + + _, err := client.ProtectedBranches.UnprotectRepositoryBranches(project, branch) + return err +} + +func projectAndBranchFromID(id string) (string, string, error) { + project, branch, err := parseTwoPartID(id) + + if err != nil { + log.Printf("[WARN] cannot get group member id from input: %v", id) + } + return project, branch, err +} From 7408b070eb6719b5bb8e9455a6cd1ffc458eefa1 Mon Sep 17 00:00:00 2001 From: Waseem Hassan Date: Wed, 24 Oct 2018 12:37:20 +0500 Subject: [PATCH 04/29] Update branch protection logic to recreate branch protection rule --- gitlab/resource_gitlab_branch_protection.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/gitlab/resource_gitlab_branch_protection.go b/gitlab/resource_gitlab_branch_protection.go index 06943de9c..c2654ff8e 100644 --- a/gitlab/resource_gitlab_branch_protection.go +++ b/gitlab/resource_gitlab_branch_protection.go @@ -46,20 +46,30 @@ func resourceGitlabBranchProtection() *schema.Resource { func resourceGitlabBranchProtectionCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*gitlab.Client) project := d.Get("project").(string) + branch := gitlab.String(d.Get("branch").(string)) mergeAccessLevel := accessLevelID[d.Get("merge_access_level").(string)] pushAccessLevel := accessLevelID[d.Get("push_access_level").(string)] options := &gitlab.ProtectRepositoryBranchesOptions{ - Name: gitlab.String(d.Get("branch").(string)), + Name: branch, MergeAccessLevel: &mergeAccessLevel, PushAccessLevel: &pushAccessLevel, } - log.Printf("[DEBUG] create gitlab branch protection on %s for project %s", options.Name, project) + log.Printf("[DEBUG] create gitlab branch protection on %v for project %s", options.Name, project) bp, _, err := client.ProtectedBranches.ProtectRepositoryBranches(project, options) if err != nil { - return err + // Remove existing branch protection + _, err = client.ProtectedBranches.UnprotectRepositoryBranches(project, *branch) + if err != nil { + return err + } + // Reprotect branch with updated values + bp, _, err = client.ProtectedBranches.ProtectRepositoryBranches(project, options) + if err != nil { + return err + } } d.SetId(buildTwoPartID(&project, &bp.Name)) From 7ca347a7677b86648074401a1c678eace6e1e4f0 Mon Sep 17 00:00:00 2001 From: Waseem Hassan Date: Wed, 24 Oct 2018 13:04:42 +0500 Subject: [PATCH 05/29] Don't update default branch --- gitlab/resource_gitlab_project.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gitlab/resource_gitlab_project.go b/gitlab/resource_gitlab_project.go index 4e34b2218..1ecf53ba7 100644 --- a/gitlab/resource_gitlab_project.go +++ b/gitlab/resource_gitlab_project.go @@ -98,7 +98,6 @@ func resourceGitlabProjectSetToState(d *schema.ResourceData, project *gitlab.Pro d.Set("name", project.Name) d.Set("path", project.Path) d.Set("description", project.Description) - d.Set("default_branch", project.DefaultBranch) d.Set("issues_enabled", project.IssuesEnabled) d.Set("merge_requests_enabled", project.MergeRequestsEnabled) d.Set("wiki_enabled", project.WikiEnabled) @@ -182,10 +181,6 @@ func resourceGitlabProjectUpdate(d *schema.ResourceData, meta interface{}) error options.Description = gitlab.String(d.Get("description").(string)) } - if d.HasChange("default_branch") { - options.DefaultBranch = gitlab.String(d.Get("default_branch").(string)) - } - if d.HasChange("visibility_level") { options.Visibility = stringToVisibilityLevel(d.Get("visibility_level").(string)) } From ad51d17431659467cc4ac34add1ec43a078f4e95 Mon Sep 17 00:00:00 2001 From: Waseem Hassan Date: Tue, 27 Nov 2018 12:10:23 +0500 Subject: [PATCH 06/29] Add default branch back --- gitlab/resource_gitlab_project.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gitlab/resource_gitlab_project.go b/gitlab/resource_gitlab_project.go index 1ecf53ba7..4e34b2218 100644 --- a/gitlab/resource_gitlab_project.go +++ b/gitlab/resource_gitlab_project.go @@ -98,6 +98,7 @@ func resourceGitlabProjectSetToState(d *schema.ResourceData, project *gitlab.Pro d.Set("name", project.Name) d.Set("path", project.Path) d.Set("description", project.Description) + d.Set("default_branch", project.DefaultBranch) d.Set("issues_enabled", project.IssuesEnabled) d.Set("merge_requests_enabled", project.MergeRequestsEnabled) d.Set("wiki_enabled", project.WikiEnabled) @@ -181,6 +182,10 @@ func resourceGitlabProjectUpdate(d *schema.ResourceData, meta interface{}) error options.Description = gitlab.String(d.Get("description").(string)) } + if d.HasChange("default_branch") { + options.DefaultBranch = gitlab.String(d.Get("default_branch").(string)) + } + if d.HasChange("visibility_level") { options.Visibility = stringToVisibilityLevel(d.Get("visibility_level").(string)) } From e646c96cb56098b0fa519a10a6c58f947b0cea90 Mon Sep 17 00:00:00 2001 From: Igor Zibarev Date: Wed, 17 Oct 2018 00:33:50 +0300 Subject: [PATCH 07/29] Add initial gitlab slack service implementation --- gitlab/import_gitlab_service_slack.go | 16 + gitlab/provider.go | 1 + gitlab/resource_gitlab_service_slack.go | 369 ++++++++++++++++++++++++ 3 files changed, 386 insertions(+) create mode 100644 gitlab/import_gitlab_service_slack.go create mode 100644 gitlab/resource_gitlab_service_slack.go diff --git a/gitlab/import_gitlab_service_slack.go b/gitlab/import_gitlab_service_slack.go new file mode 100644 index 000000000..0f191e3d4 --- /dev/null +++ b/gitlab/import_gitlab_service_slack.go @@ -0,0 +1,16 @@ +package gitlab + +import "github.com/hashicorp/terraform/helper/schema" + +// resourceGitlabServiceSlackImport is a StateFunc used to import GitLab Slack +// service by its project id. +func resourceGitlabServiceSlackImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + // Actually, integration services have their own internal ids. + // But, there is no way in GitLab API to reference any integration service + // by its id. Instead, API for services works with project id. + // Thus, this workaround allows us to import gitlab service + // by the project id. + + d.Set("project", d.Id()) + return []*schema.ResourceData{d}, nil +} diff --git a/gitlab/provider.go b/gitlab/provider.go index 40371eac2..2694fc9b1 100644 --- a/gitlab/provider.go +++ b/gitlab/provider.go @@ -60,6 +60,7 @@ func Provider() terraform.ResourceProvider { "gitlab_project_variable": resourceGitlabProjectVariable(), "gitlab_group_variable": resourceGitlabGroupVariable(), "gitlab_project_cluster": resourceGitlabProjectCluster(), + "gitlab_service_slack": resourceGitlabServiceSlack(), }, ConfigureFunc: providerConfigure, diff --git a/gitlab/resource_gitlab_service_slack.go b/gitlab/resource_gitlab_service_slack.go new file mode 100644 index 000000000..61e8b21d9 --- /dev/null +++ b/gitlab/resource_gitlab_service_slack.go @@ -0,0 +1,369 @@ +package gitlab + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/xanzy/go-gitlab" +) + +func resourceGitlabServiceSlack() *schema.Resource { + return &schema.Resource{ + Create: resourceGitlabServiceSlackCreate, + Read: resourceGitlabServiceSlackRead, + Update: resourceGitlabServiceSlackUpdate, + Delete: resourceGitlabServiceSlackDelete, + Importer: &schema.ResourceImporter{ + State: resourceGitlabServiceSlackImportState, + }, + + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + }, + "webhook": { + Type: schema.TypeString, + Required: true, + }, + "username": { + Type: schema.TypeString, + Optional: true, + }, + "notify_only_broken_pipelines": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "notify_only_default_branch": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "push_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "push_channel": { + Type: schema.TypeString, + Optional: true, + }, + "issue_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "issue_channel": { + Type: schema.TypeString, + Optional: true, + }, + "confidential_issue_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "confidential_issue_channel": { + Type: schema.TypeString, + Optional: true, + }, + "merge_request_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "merge_request_channel": { + Type: schema.TypeString, + Optional: true, + }, + "tag_push_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "tag_push_channel": { + Type: schema.TypeString, + Optional: true, + }, + "note_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "note_channel": { + Type: schema.TypeString, + Optional: true, + }, + "confidential_note_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + // TODO: Currently, GitLab ignores this option (not implemented yet?), so + // there is no way to set it. Uncomment when this is fixed. + // See: https://gitlab.com/gitlab-org/gitlab-ce/issues/49730 + //"confidential_note_channel": { + // Type: schema.TypeString, + // Optional: true, + // Computed: true, + //}, + "pipeline_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "pipeline_channel": { + Type: schema.TypeString, + Optional: true, + }, + "wiki_page_events": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "wiki_page_channel": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceGitlabServiceSlackSetToState(d *schema.ResourceData, service *gitlab.SlackService) { + if !service.Active { + log.Println("[DEBUG] slack service is not active") + d.SetId("") + return + } + + d.SetId(fmt.Sprintf("%d", service.ID)) + d.Set("webhook", service.Properties.WebHook) + d.Set("username", service.Properties.Username) + d.Set("notify_only_broken_pipelines", service.Properties.NotifyOnlyBrokenPipelines) + d.Set("notify_only_default_branch", service.Properties.NotifyOnlyDefaultBranch) + d.Set("push_events", service.PushEvents) + d.Set("push_channel", service.Properties.PushChannel) + d.Set("issue_events", service.IssuesEvents) + d.Set("issue_channel", service.Properties.IssueChannel) + d.Set("confidential_issue_events", service.ConfidentialIssuesEvents) + d.Set("confidential_issue_channel", service.Properties.ConfidentialIssueChannel) + d.Set("merge_request_events", service.MergeRequestsEvents) + d.Set("merge_request_channel", service.Properties.MergeRequestChannel) + d.Set("tag_push_events", service.TagPushEvents) + d.Set("tag_push_channel", service.Properties.TagPushChannel) + d.Set("note_events", service.NoteEvents) + d.Set("note_channel", service.Properties.NoteChannel) + d.Set("confidential_note_events", service.ConfidentialNoteEvents) + // See comment to "confidential_note_channel" in resourceGitlabServiceSlack() + //d.Set("confidential_note_channel", service.Properties.ConfidentialNoteChannel) + d.Set("pipeline_events", service.PipelineEvents) + d.Set("pipeline_channel", service.Properties.PipelineChannel) + d.Set("wiki_page_events", service.WikiPageEvents) + d.Set("wiki_page_channel", service.Properties.WikiPageChannel) +} + +func resourceGitlabServiceSlackCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + + log.Printf("[DEBUG] create gitlab slack service for project %s", project) + + opts := &gitlab.SetSlackServiceOptions{ + WebHook: gitlab.String(d.Get("webhook").(string)), + Username: gitlab.String(d.Get("username").(string)), + } + + if v, ok := d.GetOkExists("notify_only_broken_pipelines"); ok { + opts.NotifyOnlyBrokenPipelines = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOkExists("notify_only_default_branch"); ok { + opts.NotifyOnlyDefaultBranch = gitlab.Bool(v.(bool)) + } + + if v, ok := d.GetOkExists("push_events"); ok { + opts.PushEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("push_channel"); ok { + opts.PushChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("issue_events"); ok { + opts.IssuesEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("issue_channel"); ok { + opts.IssueChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("confidential_issue_events"); ok { + opts.ConfidentialIssuesEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("confidential_issue_channel"); ok { + opts.ConfidentialIssueChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("merge_request_events"); ok { + opts.MergeRequestsEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("merge_request_channel"); ok { + opts.MergeRequestChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("tag_push_events"); ok { + opts.TagPushEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("tag_push_channel"); ok { + opts.TagPushChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("note_events"); ok { + opts.NoteEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("note_channel"); ok { + opts.NoteChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("confidential_note_events"); ok { + opts.ConfidentialNoteEvents = gitlab.Bool(v.(bool)) + } + // See comment to "confidential_note_channel" in resourceGitlabServiceSlack() + //if v, ok := d.GetOk("confidential_note_channel"); ok { + // opts.ConfidentialNoteChannel = gitlab.String(v.(string)) + //} + + if v, ok := d.GetOkExists("pipeline_events"); ok { + opts.PipelineEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("pipeline_channel"); ok { + opts.PipelineChannel = gitlab.String(v.(string)) + } + + if v, ok := d.GetOkExists("wiki_page_events"); ok { + opts.WikiPageEvents = gitlab.Bool(v.(bool)) + } + if v, ok := d.GetOk("wiki_page_channel"); ok { + opts.WikiPageChannel = gitlab.String(v.(string)) + } + + _, err := client.Services.SetSlackService(project, opts) + if err != nil { + return err + } + + return resourceGitlabServiceSlackRead(d, meta) +} + +func resourceGitlabServiceSlackRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + + log.Printf("[DEBUG] read gitlab slack service for project %s", project) + + service, _, err := client.Services.GetSlackService(project) + if err != nil { + return err + } + + resourceGitlabServiceSlackSetToState(d, service) + return nil +} + +func resourceGitlabServiceSlackUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + + log.Printf("[DEBUG] update gitlab slack service for project %s", project) + + opts := &gitlab.SetSlackServiceOptions{ + WebHook: gitlab.String(d.Get("webhook").(string)), + Username: gitlab.String(d.Get("username").(string)), + } + + if d.HasChange("notify_only_broken_pipelines") { + opts.NotifyOnlyBrokenPipelines = gitlab.Bool(d.Get("notify_only_broken_pipelines").(bool)) + } + if d.HasChange("notify_only_default_branch") { + opts.NotifyOnlyDefaultBranch = gitlab.Bool(d.Get("notify_only_default_branch").(bool)) + } + + if d.HasChange("push_events") { + opts.PushEvents = gitlab.Bool(d.Get("push_events").(bool)) + } + if d.HasChange("push_channel") { + opts.PushChannel = gitlab.String(d.Get("push_channel").(string)) + } + + if d.HasChange("issue_events") { + opts.IssuesEvents = gitlab.Bool(d.Get("issue_events").(bool)) + } + if d.HasChange("issue_channel") { + opts.IssueChannel = gitlab.String(d.Get("issue_channel").(string)) + } + + if d.HasChange("confidential_issue_events") { + opts.ConfidentialIssuesEvents = gitlab.Bool(d.Get("confidential_issue_events").(bool)) + } + if d.HasChange("confidential_issue_channel") { + opts.ConfidentialIssueChannel = gitlab.String(d.Get("confidential_issue_channel").(string)) + } + + if d.HasChange("merge_request_events") { + opts.MergeRequestsEvents = gitlab.Bool(d.Get("merge_request_events").(bool)) + } + if d.HasChange("merge_request_channel") { + opts.MergeRequestChannel = gitlab.String(d.Get("merge_request_channel").(string)) + } + + if d.HasChange("tag_push_events") { + opts.TagPushEvents = gitlab.Bool(d.Get("tag_push_events").(bool)) + } + if d.HasChange("tag_push_channel") { + opts.TagPushChannel = gitlab.String(d.Get("tag_push_channel").(string)) + } + + if d.HasChange("note_events") { + opts.NoteEvents = gitlab.Bool(d.Get("note_events").(bool)) + } + if d.HasChange("note_channel") { + opts.NoteChannel = gitlab.String(d.Get("note_channel").(string)) + } + + if d.HasChange("confidential_note_events") { + opts.ConfidentialNoteEvents = gitlab.Bool(d.Get("confidential_note_events").(bool)) + } + // See comment to "confidential_note_channel" in resourceGitlabServiceSlack() + //if d.HasChange("confidential_note_channel") { + // opts.ConfidentialNoteChannel = gitlab.String(d.Get("confidential_note_channel").(string)) + //} + + if d.HasChange("pipeline_events") { + opts.PipelineEvents = gitlab.Bool(d.Get("pipeline_events").(bool)) + } + if d.HasChange("pipeline_channel") { + opts.PipelineChannel = gitlab.String(d.Get("pipeline_channel").(string)) + } + + if d.HasChange("wiki_page_events") { + opts.WikiPageEvents = gitlab.Bool(d.Get("wiki_page_events").(bool)) + } + if d.HasChange("wiki_page_channel") { + opts.WikiPageChannel = gitlab.String(d.Get("wiki_page_channel").(string)) + } + + _, err := client.Services.SetSlackService(project, opts) + if err != nil { + return err + } + + return resourceGitlabServiceSlackRead(d, meta) +} + +func resourceGitlabServiceSlackDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + + log.Printf("[DEBUG] delete gitlab slack service for project %s", project) + + _, err := client.Services.DeleteSlackService(project) + return err +} From cae98b9dfa45049568b56b27db05f19060b30b80 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Tue, 22 Jan 2019 14:49:52 +0100 Subject: [PATCH 08/29] Update slack service resource: rebase on go-gitlab vendor update, add new attributes and fix others attributes' name --- gitlab/resource_gitlab_service_slack.go | 63 ++++++++++++++----------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/gitlab/resource_gitlab_service_slack.go b/gitlab/resource_gitlab_service_slack.go index 61e8b21d9..775e026d3 100644 --- a/gitlab/resource_gitlab_service_slack.go +++ b/gitlab/resource_gitlab_service_slack.go @@ -5,7 +5,7 @@ import ( "log" "github.com/hashicorp/terraform/helper/schema" - "github.com/xanzy/go-gitlab" + gitlab "github.com/xanzy/go-gitlab" ) func resourceGitlabServiceSlack() *schema.Resource { @@ -50,7 +50,7 @@ func resourceGitlabServiceSlack() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "issue_events": { + "issues_events": { Type: schema.TypeBool, Optional: true, Computed: true, @@ -59,7 +59,7 @@ func resourceGitlabServiceSlack() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "confidential_issue_events": { + "confidential_issues_events": { Type: schema.TypeBool, Optional: true, Computed: true, @@ -68,7 +68,7 @@ func resourceGitlabServiceSlack() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "merge_request_events": { + "merge_requests_events": { Type: schema.TypeBool, Optional: true, Computed: true, @@ -126,6 +126,10 @@ func resourceGitlabServiceSlack() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "job_events": { + Type: schema.TypeBool, + Computed: true, + }, }, } } @@ -140,15 +144,15 @@ func resourceGitlabServiceSlackSetToState(d *schema.ResourceData, service *gitla d.SetId(fmt.Sprintf("%d", service.ID)) d.Set("webhook", service.Properties.WebHook) d.Set("username", service.Properties.Username) - d.Set("notify_only_broken_pipelines", service.Properties.NotifyOnlyBrokenPipelines) - d.Set("notify_only_default_branch", service.Properties.NotifyOnlyDefaultBranch) + d.Set("notify_only_broken_pipelines", service.Properties.NotifyOnlyBrokenPipelines.UnmarshalJSON) + d.Set("notify_only_default_branch", service.Properties.NotifyOnlyDefaultBranch.UnmarshalJSON) d.Set("push_events", service.PushEvents) d.Set("push_channel", service.Properties.PushChannel) - d.Set("issue_events", service.IssuesEvents) + d.Set("issues_events", service.IssuesEvents) d.Set("issue_channel", service.Properties.IssueChannel) - d.Set("confidential_issue_events", service.ConfidentialIssuesEvents) + d.Set("confidential_issues_events", service.ConfidentialIssuesEvents) d.Set("confidential_issue_channel", service.Properties.ConfidentialIssueChannel) - d.Set("merge_request_events", service.MergeRequestsEvents) + d.Set("merge_requests_events", service.MergeRequestsEvents) d.Set("merge_request_channel", service.Properties.MergeRequestChannel) d.Set("tag_push_events", service.TagPushEvents) d.Set("tag_push_channel", service.Properties.TagPushChannel) @@ -161,6 +165,7 @@ func resourceGitlabServiceSlackSetToState(d *schema.ResourceData, service *gitla d.Set("pipeline_channel", service.Properties.PipelineChannel) d.Set("wiki_page_events", service.WikiPageEvents) d.Set("wiki_page_channel", service.Properties.WikiPageChannel) + d.Set("job_events", service.JobEvents) } func resourceGitlabServiceSlackCreate(d *schema.ResourceData, meta interface{}) error { @@ -170,60 +175,62 @@ func resourceGitlabServiceSlackCreate(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] create gitlab slack service for project %s", project) opts := &gitlab.SetSlackServiceOptions{ - WebHook: gitlab.String(d.Get("webhook").(string)), - Username: gitlab.String(d.Get("username").(string)), + WebHook: gitlab.String(d.Get("webhook").(string)), } - if v, ok := d.GetOkExists("notify_only_broken_pipelines"); ok { + if v := d.Get("username"); v != nil { + opts.Username = gitlab.String(v.(string)) + } + if v := d.Get("notify_only_broken_pipelines"); v != nil { opts.NotifyOnlyBrokenPipelines = gitlab.Bool(v.(bool)) } - if v, ok := d.GetOkExists("notify_only_default_branch"); ok { + if v := d.Get("notify_only_default_branch"); v != nil { opts.NotifyOnlyDefaultBranch = gitlab.Bool(v.(bool)) } - if v, ok := d.GetOkExists("push_events"); ok { + if v := d.Get("push_events"); v != nil { opts.PushEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("push_channel"); ok { opts.PushChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("issue_events"); ok { + if v := d.Get("issues_events"); v != nil { opts.IssuesEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("issue_channel"); ok { opts.IssueChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("confidential_issue_events"); ok { + if v := d.Get("confidential_issues_events"); v != nil { opts.ConfidentialIssuesEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("confidential_issue_channel"); ok { opts.ConfidentialIssueChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("merge_request_events"); ok { + if v := d.Get("merge_requests_events"); v != nil { opts.MergeRequestsEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("merge_request_channel"); ok { opts.MergeRequestChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("tag_push_events"); ok { + if v := d.Get("tag_push_events"); v != nil { opts.TagPushEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("tag_push_channel"); ok { opts.TagPushChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("note_events"); ok { + if v := d.Get("note_events"); v != nil { opts.NoteEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("note_channel"); ok { opts.NoteChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("confidential_note_events"); ok { + if v := d.Get("confidential_note_events"); v != nil { opts.ConfidentialNoteEvents = gitlab.Bool(v.(bool)) } // See comment to "confidential_note_channel" in resourceGitlabServiceSlack() @@ -231,14 +238,14 @@ func resourceGitlabServiceSlackCreate(d *schema.ResourceData, meta interface{}) // opts.ConfidentialNoteChannel = gitlab.String(v.(string)) //} - if v, ok := d.GetOkExists("pipeline_events"); ok { + if v := d.Get("pipeline_events"); v != nil { opts.PipelineEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("pipeline_channel"); ok { opts.PipelineChannel = gitlab.String(v.(string)) } - if v, ok := d.GetOkExists("wiki_page_events"); ok { + if v := d.Get("wiki_page_events"); v != nil { opts.WikiPageEvents = gitlab.Bool(v.(bool)) } if v, ok := d.GetOk("wiki_page_channel"); ok { @@ -293,22 +300,22 @@ func resourceGitlabServiceSlackUpdate(d *schema.ResourceData, meta interface{}) opts.PushChannel = gitlab.String(d.Get("push_channel").(string)) } - if d.HasChange("issue_events") { - opts.IssuesEvents = gitlab.Bool(d.Get("issue_events").(bool)) + if d.HasChange("issues_events") { + opts.IssuesEvents = gitlab.Bool(d.Get("issues_events").(bool)) } if d.HasChange("issue_channel") { opts.IssueChannel = gitlab.String(d.Get("issue_channel").(string)) } - if d.HasChange("confidential_issue_events") { - opts.ConfidentialIssuesEvents = gitlab.Bool(d.Get("confidential_issue_events").(bool)) + if d.HasChange("confidential_issues_events") { + opts.ConfidentialIssuesEvents = gitlab.Bool(d.Get("confidential_issues_events").(bool)) } if d.HasChange("confidential_issue_channel") { opts.ConfidentialIssueChannel = gitlab.String(d.Get("confidential_issue_channel").(string)) } - if d.HasChange("merge_request_events") { - opts.MergeRequestsEvents = gitlab.Bool(d.Get("merge_request_events").(bool)) + if d.HasChange("merge_requests_events") { + opts.MergeRequestsEvents = gitlab.Bool(d.Get("merge_requests_events").(bool)) } if d.HasChange("merge_request_channel") { opts.MergeRequestChannel = gitlab.String(d.Get("merge_request_channel").(string)) From d34380c0a0865023897304016ff217f6f3cbf2a8 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Tue, 22 Jan 2019 14:51:15 +0100 Subject: [PATCH 09/29] Update slack service resource: refactor update function --- gitlab/resource_gitlab_service_slack.go | 88 +------------------------ 1 file changed, 1 insertion(+), 87 deletions(-) diff --git a/gitlab/resource_gitlab_service_slack.go b/gitlab/resource_gitlab_service_slack.go index 775e026d3..bc8da54b6 100644 --- a/gitlab/resource_gitlab_service_slack.go +++ b/gitlab/resource_gitlab_service_slack.go @@ -276,93 +276,7 @@ func resourceGitlabServiceSlackRead(d *schema.ResourceData, meta interface{}) er } func resourceGitlabServiceSlackUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*gitlab.Client) - project := d.Get("project").(string) - - log.Printf("[DEBUG] update gitlab slack service for project %s", project) - - opts := &gitlab.SetSlackServiceOptions{ - WebHook: gitlab.String(d.Get("webhook").(string)), - Username: gitlab.String(d.Get("username").(string)), - } - - if d.HasChange("notify_only_broken_pipelines") { - opts.NotifyOnlyBrokenPipelines = gitlab.Bool(d.Get("notify_only_broken_pipelines").(bool)) - } - if d.HasChange("notify_only_default_branch") { - opts.NotifyOnlyDefaultBranch = gitlab.Bool(d.Get("notify_only_default_branch").(bool)) - } - - if d.HasChange("push_events") { - opts.PushEvents = gitlab.Bool(d.Get("push_events").(bool)) - } - if d.HasChange("push_channel") { - opts.PushChannel = gitlab.String(d.Get("push_channel").(string)) - } - - if d.HasChange("issues_events") { - opts.IssuesEvents = gitlab.Bool(d.Get("issues_events").(bool)) - } - if d.HasChange("issue_channel") { - opts.IssueChannel = gitlab.String(d.Get("issue_channel").(string)) - } - - if d.HasChange("confidential_issues_events") { - opts.ConfidentialIssuesEvents = gitlab.Bool(d.Get("confidential_issues_events").(bool)) - } - if d.HasChange("confidential_issue_channel") { - opts.ConfidentialIssueChannel = gitlab.String(d.Get("confidential_issue_channel").(string)) - } - - if d.HasChange("merge_requests_events") { - opts.MergeRequestsEvents = gitlab.Bool(d.Get("merge_requests_events").(bool)) - } - if d.HasChange("merge_request_channel") { - opts.MergeRequestChannel = gitlab.String(d.Get("merge_request_channel").(string)) - } - - if d.HasChange("tag_push_events") { - opts.TagPushEvents = gitlab.Bool(d.Get("tag_push_events").(bool)) - } - if d.HasChange("tag_push_channel") { - opts.TagPushChannel = gitlab.String(d.Get("tag_push_channel").(string)) - } - - if d.HasChange("note_events") { - opts.NoteEvents = gitlab.Bool(d.Get("note_events").(bool)) - } - if d.HasChange("note_channel") { - opts.NoteChannel = gitlab.String(d.Get("note_channel").(string)) - } - - if d.HasChange("confidential_note_events") { - opts.ConfidentialNoteEvents = gitlab.Bool(d.Get("confidential_note_events").(bool)) - } - // See comment to "confidential_note_channel" in resourceGitlabServiceSlack() - //if d.HasChange("confidential_note_channel") { - // opts.ConfidentialNoteChannel = gitlab.String(d.Get("confidential_note_channel").(string)) - //} - - if d.HasChange("pipeline_events") { - opts.PipelineEvents = gitlab.Bool(d.Get("pipeline_events").(bool)) - } - if d.HasChange("pipeline_channel") { - opts.PipelineChannel = gitlab.String(d.Get("pipeline_channel").(string)) - } - - if d.HasChange("wiki_page_events") { - opts.WikiPageEvents = gitlab.Bool(d.Get("wiki_page_events").(bool)) - } - if d.HasChange("wiki_page_channel") { - opts.WikiPageChannel = gitlab.String(d.Get("wiki_page_channel").(string)) - } - - _, err := client.Services.SetSlackService(project, opts) - if err != nil { - return err - } - - return resourceGitlabServiceSlackRead(d, meta) + return resourceGitlabServiceSlackCreate(d, meta) } func resourceGitlabServiceSlackDelete(d *schema.ResourceData, meta interface{}) error { From b71f32a07586a9be4e7c22be6231d95e58929355 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Tue, 22 Jan 2019 14:54:32 +0100 Subject: [PATCH 10/29] Update slack service resource: improve read func: handle 404 --- gitlab/resource_gitlab_service_slack.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gitlab/resource_gitlab_service_slack.go b/gitlab/resource_gitlab_service_slack.go index bc8da54b6..ac7099c34 100644 --- a/gitlab/resource_gitlab_service_slack.go +++ b/gitlab/resource_gitlab_service_slack.go @@ -266,12 +266,18 @@ func resourceGitlabServiceSlackRead(d *schema.ResourceData, meta interface{}) er log.Printf("[DEBUG] read gitlab slack service for project %s", project) - service, _, err := client.Services.GetSlackService(project) + service, response, err := client.Services.GetSlackService(project) if err != nil { + if response.StatusCode == 404 { + log.Printf("[WARN] removing Slack service from state because it no longer exists in Gitlab") + d.SetId("") + return nil + } return err } resourceGitlabServiceSlackSetToState(d, service) + return nil } From 8fd788681384f7a05c9794aff5be1469425d6aaa Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Mon, 14 Jan 2019 18:21:26 +0100 Subject: [PATCH 11/29] Add slack service tests --- gitlab/resource_gitlab_service_slack_test.go | 175 +++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 gitlab/resource_gitlab_service_slack_test.go diff --git a/gitlab/resource_gitlab_service_slack_test.go b/gitlab/resource_gitlab_service_slack_test.go new file mode 100644 index 000000000..134dce022 --- /dev/null +++ b/gitlab/resource_gitlab_service_slack_test.go @@ -0,0 +1,175 @@ +package gitlab + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + gitlab "github.com/xanzy/go-gitlab" +) + +func TestAccGitlabServiceSlack_basic(t *testing.T) { + var service gitlab.SlackService + rInt := acctest.RandInt() + slackResourceName := "gitlab_service_slack.slack" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGitlabServiceDestroy, + Steps: []resource.TestStep{ + // Create a project and a slack service + { + Config: testAccGitlabServiceSlackConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabServiceExists(slackResourceName, &service), + resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://test.com"), + resource.TestCheckResourceAttr(slackResourceName, "push_events", "true"), + resource.TestCheckResourceAttr(slackResourceName, "push_channel", "test"), + ), + }, + // Update the slack service + { + Config: testAccGitlabServiceSlackUpdateConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabServiceExists(slackResourceName, &service), + resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://testwebhook.com"), + resource.TestCheckResourceAttr(slackResourceName, "push_events", "false"), + resource.TestCheckResourceAttr(slackResourceName, "push_channel", "test push_channel"), + ), + }, + // Update the slack service to get back to initial settings + { + Config: testAccGitlabServiceSlackConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabServiceExists(slackResourceName, &service), + resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://test.com"), + resource.TestCheckResourceAttr(slackResourceName, "push_events", "true"), + resource.TestCheckResourceAttr(slackResourceName, "push_channel", "test"), + ), + }, + }, + }) +} + +func testAccCheckGitlabServiceExists(n string, service *gitlab.SlackService) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not Found: %s", n) + } + + project := rs.Primary.Attributes["project"] + if project == "" { + return fmt.Errorf("No project ID is set") + } + conn := testAccProvider.Meta().(*gitlab.Client) + + _, _, err := conn.Services.GetSlackService(project) + if err != nil { + return fmt.Errorf("Slack service does not exist in project %s: %v", project, err) + } + + return nil + } +} + +func testAccCheckGitlabServiceDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*gitlab.Client) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "gitlab_project" { + continue + } + + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + if err == nil { + if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { + return fmt.Errorf("Repository still exists") + } + } + if resp.StatusCode != 404 { + return err + } + return nil + } + return nil +} + +func testAccGitlabServiceSlackConfig(rInt int) string { + return fmt.Sprintf(` +resource "gitlab_project" "foo" { + name = "foo-%d" + description = "Terraform acceptance tests" + + # So that acceptance tests can be run in a gitlab organization + # with no billing + visibility_level = "public" +} + +resource "gitlab_service_slack" "slack" { + project = "${gitlab_project.foo.id}" + webhook = "https://test.com" + username = "test" + push_events = true + push_channel = "test" + issues_events = true + issue_channel = "test" + confidential_issues_events = true + confidential_issue_channel = "test" + confidential_note_events = true + merge_requests_events = true + merge_request_channel = "test" + tag_push_events = true + tag_push_channel = "test" + note_events = true + note_channel = "test" + pipeline_events = true + pipeline_channel = "test" + wiki_page_events = true + wiki_page_channel = "test" + notify_only_broken_pipelines = true + notify_only_default_branch = true +} +`, rInt) +} + +func testAccGitlabServiceSlackUpdateConfig(rInt int) string { + return fmt.Sprintf(` +resource "gitlab_project" "foo" { + name = "foo-%d" + description = "Terraform acceptance tests" + + # So that acceptance tests can be run in a gitlab organization + # with no billing + visibility_level = "public" +} + +resource "gitlab_service_slack" "slack" { + project = "${gitlab_project.foo.id}" + webhook = "https://testwebhook.com" + username = "test username" + push_events = false + push_channel = "test push_channel" + issues_events = false + issue_channel = "test issue_channel" + confidential_issues_events = false + confidential_issue_channel = "test confidential_issue_channel" + confidential_note_events = false + merge_requests_events = false + merge_request_channel = "test merge_request_channel" + tag_push_events = false + tag_push_channel = "test tag_push_channel" + note_events = false + note_channel = "test note_channel" + pipeline_events = false + pipeline_channel = "test pipeline_channel" + wiki_page_events = false + wiki_page_channel = "test wiki_page_channel" + notify_only_broken_pipelines = false + notify_only_default_branch = false +} +`, rInt) +} From da07f0f123fd067c6a5a65fe08d875b2e3830869 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Sun, 10 Feb 2019 14:28:07 +0100 Subject: [PATCH 12/29] Update deploy key resource: allow imports --- gitlab/resource_gitlab_deploy_key.go | 17 +++++++++ gitlab/resource_gitlab_deploy_key_test.go | 46 ++++++++++++++++++++++- website/docs/r/deploy_key.html.markdown | 8 ++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/gitlab/resource_gitlab_deploy_key.go b/gitlab/resource_gitlab_deploy_key.go index 0a4ce6a55..58c32639a 100644 --- a/gitlab/resource_gitlab_deploy_key.go +++ b/gitlab/resource_gitlab_deploy_key.go @@ -15,6 +15,9 @@ func resourceGitlabDeployKey() *schema.Resource { Create: resourceGitlabDeployKeyCreate, Read: resourceGitlabDeployKeyRead, Delete: resourceGitlabDeployKeyDelete, + Importer: &schema.ResourceImporter{ + State: resourceGitlabDeployKeyStateImporter, + }, Schema: map[string]*schema.Schema{ "project": { @@ -109,3 +112,17 @@ func resourceGitlabDeployKeyDelete(d *schema.ResourceData, meta interface{}) err } return err } + +func resourceGitlabDeployKeyStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + s := strings.Split(d.Id(), ":") + if len(s) != 2 { + d.SetId("") + return nil, fmt.Errorf("Invalid Deploy Key import format; expected '{project_id}:{deploy_key_id}'") + } + project, id := s[0], s[1] + + d.SetId(id) + d.Set("project", project) + + return []*schema.ResourceData{d}, nil +} diff --git a/gitlab/resource_gitlab_deploy_key_test.go b/gitlab/resource_gitlab_deploy_key_test.go index ef814ca01..52e2ef494 100644 --- a/gitlab/resource_gitlab_deploy_key_test.go +++ b/gitlab/resource_gitlab_deploy_key_test.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/xanzy/go-gitlab" + gitlab "github.com/xanzy/go-gitlab" ) func TestAccGitlabDeployKey_basic(t *testing.T) { @@ -67,7 +67,29 @@ func TestAccGitlabDeployKey_suppressfunc(t *testing.T) { Steps: []resource.TestStep{ // Create a project and deployKey with newline as suffix { - Config: testAccGitlabDeployKeyConfig(rInt, "\\n"), + Config: testAccGitlabDeployKeyConfig(rInt, ""), + }, + }, + }) +} + +func TestAccGitlabDeployKey_import(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "gitlab_deploy_key.foo" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGitlabDeployKeyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGitlabDeployKeyConfig(rInt, ""), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: getDeployKeyImportID(resourceName), + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -147,6 +169,26 @@ func testAccCheckGitlabDeployKeyDestroy(s *terraform.State) error { return nil } +func getDeployKeyImportID(n string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[n] + if !ok { + return "", fmt.Errorf("Not Found: %s", n) + } + + deployKeyID := rs.Primary.ID + if deployKeyID == "" { + return "", fmt.Errorf("No deploy key ID is set") + } + projectID := rs.Primary.Attributes["project"] + if projectID == "" { + return "", fmt.Errorf("No project ID is set") + } + + return fmt.Sprintf("%s:%s", projectID, deployKeyID), nil + } +} + func testAccGitlabDeployKeyConfig(rInt int, suffix string) string { return fmt.Sprintf(` resource "gitlab_project" "foo" { diff --git a/website/docs/r/deploy_key.html.markdown b/website/docs/r/deploy_key.html.markdown index 9868ced2e..b178e8d86 100644 --- a/website/docs/r/deploy_key.html.markdown +++ b/website/docs/r/deploy_key.html.markdown @@ -32,3 +32,11 @@ The following arguments are supported: * `key` - (Required, string) The public ssh key body. * `can_push` - (Optional, boolean) Allow this deploy key to be used to push changes to the project. Defaults to `false`. **NOTE::** this cannot currently be managed. + +## Import + +GitLab deploy keys can be imported using an id made up of `{project_id}:{deploy_key_id}`, e.g. + +``` +$ terraform import gitlab_deploy_key.test 1:3 +``` \ No newline at end of file From 8fd3ac9c686723075900d16d71348578d0f7f1e5 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Tue, 22 Jan 2019 16:23:59 +0100 Subject: [PATCH 13/29] Add slack service resource doc --- website/docs/r/service_slack.html.markdown | 85 ++++++++++++++++++++++ website/gitlab.erb | 3 + 2 files changed, 88 insertions(+) create mode 100644 website/docs/r/service_slack.html.markdown diff --git a/website/docs/r/service_slack.html.markdown b/website/docs/r/service_slack.html.markdown new file mode 100644 index 000000000..37f78bf9e --- /dev/null +++ b/website/docs/r/service_slack.html.markdown @@ -0,0 +1,85 @@ +--- +layout: "gitlab" +page_title: "GitLab: gitlab_service_slack" +sidebar_current: "docs-gitlab-resource-service_slack" +description: |- + Manage Slack notifications integration that allows to receive event notifications in Slack +--- + +# gitlab\_service_slack + +This resource allows you to manage Slack notifications integration. + +## Example Usage + +```hcl +resource "gitlab_project" "awesome_project" { + name = "awesome_project" + description = "My awesome project." + visibility_level = "public" +} + +resource "gitlab_service_slack" "slack" { + project = "${gitlab_project.awesome_project.id}" + webhook = "https://webhook.com" + username = "myuser" + push_events = true + push_channel = "push_chan" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - (Required) ID of the project you want to activate integration on. + +* `webhook` - (Required) Webhook URL (ex.: https://hooks.slack.com/services/...) + +* `username` - (Optional) Username to use. + +* `notify_only_broken_pipelines` - (Optional) Send notifications for broken pipelines. + +* `notify_only_default_branch` - (Optional) Send notifications only for the default branch. + +* `push_events` - (Optional) Enable notifications for push events. + +* `push_channel` - (Optional) The name of the channel to receive push events notifications. + +* `issues_events` - (Optional) Enable notifications for issues events. + +* `issue_channel` - (Optional) The name of the channel to receive issue events notifications. + +* `confidential_issues_events` - (Optional) Enable notifications for confidential issues events. + +* `confidential_issue_channel` - (Optional) The name of the channel to receive confidential issue events notifications. + +* `merge_requests_events` - (Optional) Enable notifications for merge requests events. + +* `merge_request_channel` - (Optional) The name of the channel to receive merge request events notifications. + +* `tag_push_events` - (Optional) Enable notifications for tag push events. + +* `tag_push_channel` - (Optional) The name of the channel to receive tag push events notifications. + +* `note_events` - (Optional) Enable notifications for note events. + +* `note_channel` - (Optional) The name of the channel to receive note events notifications. + +* `confidential_note_events` - (Optional) Enable notifications for confidential note events. + +* `pipeline_events` - (Optional) Enable notifications for pipeline events. + +* `pipeline_channel` - (Optional) The name of the channel to receive pipeline events notifications. + +* `wiki_page_events` - (Optional) Enable notifications for wiki page events. + +* `wiki_page_channel` - (Optional) The name of the channel to receive wiki page events notifications. + +## Importing Slack service + +You can import a service_slack state using `terraform import `: + +```bash +$ terraform import gitlab_service_slack.slack 1 +``` diff --git a/website/gitlab.erb b/website/gitlab.erb index 512081f8c..6589806b7 100644 --- a/website/gitlab.erb +++ b/website/gitlab.erb @@ -64,6 +64,9 @@ > gitlab_user + > + gitlab_service_slack + From a8e6a0be5f8e980dea29a9c9377fa3a077033d32 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Mon, 4 Mar 2019 10:57:40 +0100 Subject: [PATCH 14/29] Update slack service tests: add import and improvments --- gitlab/import_gitlab_service_slack.go | 16 ---- gitlab/resource_gitlab_service_slack.go | 12 +-- gitlab/resource_gitlab_service_slack_test.go | 88 ++++++++++++++++++-- 3 files changed, 86 insertions(+), 30 deletions(-) delete mode 100644 gitlab/import_gitlab_service_slack.go diff --git a/gitlab/import_gitlab_service_slack.go b/gitlab/import_gitlab_service_slack.go deleted file mode 100644 index 0f191e3d4..000000000 --- a/gitlab/import_gitlab_service_slack.go +++ /dev/null @@ -1,16 +0,0 @@ -package gitlab - -import "github.com/hashicorp/terraform/helper/schema" - -// resourceGitlabServiceSlackImport is a StateFunc used to import GitLab Slack -// service by its project id. -func resourceGitlabServiceSlackImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - // Actually, integration services have their own internal ids. - // But, there is no way in GitLab API to reference any integration service - // by its id. Instead, API for services works with project id. - // Thus, this workaround allows us to import gitlab service - // by the project id. - - d.Set("project", d.Id()) - return []*schema.ResourceData{d}, nil -} diff --git a/gitlab/resource_gitlab_service_slack.go b/gitlab/resource_gitlab_service_slack.go index ac7099c34..cb783744d 100644 --- a/gitlab/resource_gitlab_service_slack.go +++ b/gitlab/resource_gitlab_service_slack.go @@ -135,12 +135,6 @@ func resourceGitlabServiceSlack() *schema.Resource { } func resourceGitlabServiceSlackSetToState(d *schema.ResourceData, service *gitlab.SlackService) { - if !service.Active { - log.Println("[DEBUG] slack service is not active") - d.SetId("") - return - } - d.SetId(fmt.Sprintf("%d", service.ID)) d.Set("webhook", service.Properties.WebHook) d.Set("username", service.Properties.Username) @@ -294,3 +288,9 @@ func resourceGitlabServiceSlackDelete(d *schema.ResourceData, meta interface{}) _, err := client.Services.DeleteSlackService(project) return err } + +func resourceGitlabServiceSlackImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + d.Set("project", d.Id()) + + return []*schema.ResourceData{d}, nil +} diff --git a/gitlab/resource_gitlab_service_slack_test.go b/gitlab/resource_gitlab_service_slack_test.go index 134dce022..505bd4721 100644 --- a/gitlab/resource_gitlab_service_slack_test.go +++ b/gitlab/resource_gitlab_service_slack_test.go @@ -11,49 +11,86 @@ import ( ) func TestAccGitlabServiceSlack_basic(t *testing.T) { - var service gitlab.SlackService + var slackService gitlab.SlackService rInt := acctest.RandInt() slackResourceName := "gitlab_service_slack.slack" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testAccCheckGitlabServiceDestroy, + CheckDestroy: testAccCheckGitlabServiceSlackDestroy, Steps: []resource.TestStep{ - // Create a project and a slack service + // Create a project and a slack service with minimal settings + { + Config: testAccGitlabServiceSlackMinimalConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabServiceExists(slackResourceName, &slackService), + resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://test.com"), + ), + }, + // Update slack service with more settings { Config: testAccGitlabServiceSlackConfig(rInt), Check: resource.ComposeTestCheckFunc( - testAccCheckGitlabServiceExists(slackResourceName, &service), + testAccCheckGitlabServiceExists(slackResourceName, &slackService), resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://test.com"), resource.TestCheckResourceAttr(slackResourceName, "push_events", "true"), resource.TestCheckResourceAttr(slackResourceName, "push_channel", "test"), + resource.TestCheckResourceAttr(slackResourceName, "notify_only_broken_pipelines", "true"), ), }, // Update the slack service { Config: testAccGitlabServiceSlackUpdateConfig(rInt), Check: resource.ComposeTestCheckFunc( - testAccCheckGitlabServiceExists(slackResourceName, &service), + testAccCheckGitlabServiceExists(slackResourceName, &slackService), resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://testwebhook.com"), resource.TestCheckResourceAttr(slackResourceName, "push_events", "false"), resource.TestCheckResourceAttr(slackResourceName, "push_channel", "test push_channel"), + resource.TestCheckResourceAttr(slackResourceName, "notify_only_broken_pipelines", "false"), ), }, // Update the slack service to get back to initial settings { Config: testAccGitlabServiceSlackConfig(rInt), Check: resource.ComposeTestCheckFunc( - testAccCheckGitlabServiceExists(slackResourceName, &service), + testAccCheckGitlabServiceExists(slackResourceName, &slackService), resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://test.com"), resource.TestCheckResourceAttr(slackResourceName, "push_events", "true"), resource.TestCheckResourceAttr(slackResourceName, "push_channel", "test"), + resource.TestCheckResourceAttr(slackResourceName, "notify_only_broken_pipelines", "true"), ), }, }, }) } +func TestAccGitlabServiceSlack_import(t *testing.T) { + slackResourceName := "gitlab_service_slack.slack" + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGitlabServiceSlackDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGitlabServiceSlackConfig(rInt), + }, + { + ResourceName: slackResourceName, + ImportStateIdFunc: getSlackProjectID(slackResourceName), + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "notify_only_broken_pipelines", + "notify_only_default_branch", + }, + }, + }, + }) +} + func testAccCheckGitlabServiceExists(n string, service *gitlab.SlackService) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -67,16 +104,17 @@ func testAccCheckGitlabServiceExists(n string, service *gitlab.SlackService) res } conn := testAccProvider.Meta().(*gitlab.Client) - _, _, err := conn.Services.GetSlackService(project) + slackService, _, err := conn.Services.GetSlackService(project) if err != nil { return fmt.Errorf("Slack service does not exist in project %s: %v", project, err) } + *service = *slackService return nil } } -func testAccCheckGitlabServiceDestroy(s *terraform.State) error { +func testAccCheckGitlabServiceSlackDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*gitlab.Client) for _, rs := range s.RootModule().Resources { @@ -98,6 +136,40 @@ func testAccCheckGitlabServiceDestroy(s *terraform.State) error { return nil } +func getSlackProjectID(n string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[n] + if !ok { + return "", fmt.Errorf("Not Found: %s", n) + } + + project := rs.Primary.Attributes["project"] + if project == "" { + return "", fmt.Errorf("No project ID is set") + } + + return project, nil + } +} + +func testAccGitlabServiceSlackMinimalConfig(rInt int) string { + return fmt.Sprintf(` +resource "gitlab_project" "foo" { + name = "foo-%d" + description = "Terraform acceptance tests" + + # So that acceptance tests can be run in a gitlab organization + # with no billing + visibility_level = "public" +} + +resource "gitlab_service_slack" "slack" { + project = "${gitlab_project.foo.id}" + webhook = "https://test.com" +} +`, rInt) +} + func testAccGitlabServiceSlackConfig(rInt int) string { return fmt.Sprintf(` resource "gitlab_project" "foo" { From 6dfd2cb234b210bc520d3ed4d5b0610d4f02468f Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Tue, 5 Mar 2019 18:19:35 +0100 Subject: [PATCH 15/29] Update slack service: fix parameters not updated when removed --- gitlab/resource_gitlab_service_slack.go | 93 +++++--------------- gitlab/resource_gitlab_service_slack_test.go | 11 ++- 2 files changed, 30 insertions(+), 74 deletions(-) diff --git a/gitlab/resource_gitlab_service_slack.go b/gitlab/resource_gitlab_service_slack.go index cb783744d..bf70b7d07 100644 --- a/gitlab/resource_gitlab_service_slack.go +++ b/gitlab/resource_gitlab_service_slack.go @@ -172,79 +172,26 @@ func resourceGitlabServiceSlackCreate(d *schema.ResourceData, meta interface{}) WebHook: gitlab.String(d.Get("webhook").(string)), } - if v := d.Get("username"); v != nil { - opts.Username = gitlab.String(v.(string)) - } - if v := d.Get("notify_only_broken_pipelines"); v != nil { - opts.NotifyOnlyBrokenPipelines = gitlab.Bool(v.(bool)) - } - if v := d.Get("notify_only_default_branch"); v != nil { - opts.NotifyOnlyDefaultBranch = gitlab.Bool(v.(bool)) - } - - if v := d.Get("push_events"); v != nil { - opts.PushEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("push_channel"); ok { - opts.PushChannel = gitlab.String(v.(string)) - } - - if v := d.Get("issues_events"); v != nil { - opts.IssuesEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("issue_channel"); ok { - opts.IssueChannel = gitlab.String(v.(string)) - } - - if v := d.Get("confidential_issues_events"); v != nil { - opts.ConfidentialIssuesEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("confidential_issue_channel"); ok { - opts.ConfidentialIssueChannel = gitlab.String(v.(string)) - } - - if v := d.Get("merge_requests_events"); v != nil { - opts.MergeRequestsEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("merge_request_channel"); ok { - opts.MergeRequestChannel = gitlab.String(v.(string)) - } - - if v := d.Get("tag_push_events"); v != nil { - opts.TagPushEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("tag_push_channel"); ok { - opts.TagPushChannel = gitlab.String(v.(string)) - } - - if v := d.Get("note_events"); v != nil { - opts.NoteEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("note_channel"); ok { - opts.NoteChannel = gitlab.String(v.(string)) - } - - if v := d.Get("confidential_note_events"); v != nil { - opts.ConfidentialNoteEvents = gitlab.Bool(v.(bool)) - } - // See comment to "confidential_note_channel" in resourceGitlabServiceSlack() - //if v, ok := d.GetOk("confidential_note_channel"); ok { - // opts.ConfidentialNoteChannel = gitlab.String(v.(string)) - //} - - if v := d.Get("pipeline_events"); v != nil { - opts.PipelineEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("pipeline_channel"); ok { - opts.PipelineChannel = gitlab.String(v.(string)) - } - - if v := d.Get("wiki_page_events"); v != nil { - opts.WikiPageEvents = gitlab.Bool(v.(bool)) - } - if v, ok := d.GetOk("wiki_page_channel"); ok { - opts.WikiPageChannel = gitlab.String(v.(string)) - } + opts.Username = gitlab.String(d.Get("username").(string)) + opts.NotifyOnlyBrokenPipelines = gitlab.Bool(d.Get("notify_only_broken_pipelines").(bool)) + opts.NotifyOnlyDefaultBranch = gitlab.Bool(d.Get("notify_only_default_branch").(bool)) + opts.PushEvents = gitlab.Bool(d.Get("push_events").(bool)) + opts.PushChannel = gitlab.String(d.Get("push_channel").(string)) + opts.IssuesEvents = gitlab.Bool(d.Get("issues_events").(bool)) + opts.IssueChannel = gitlab.String(d.Get("issue_channel").(string)) + opts.ConfidentialIssuesEvents = gitlab.Bool(d.Get("confidential_issues_events").(bool)) + opts.ConfidentialIssueChannel = gitlab.String(d.Get("confidential_issue_channel").(string)) + opts.MergeRequestsEvents = gitlab.Bool(d.Get("merge_requests_events").(bool)) + opts.MergeRequestChannel = gitlab.String(d.Get("merge_request_channel").(string)) + opts.TagPushEvents = gitlab.Bool(d.Get("tag_push_events").(bool)) + opts.TagPushChannel = gitlab.String(d.Get("tag_push_channel").(string)) + opts.NoteEvents = gitlab.Bool(d.Get("note_events").(bool)) + opts.NoteChannel = gitlab.String(d.Get("note_channel").(string)) + opts.ConfidentialNoteEvents = gitlab.Bool(d.Get("confidential_note_events").(bool)) + opts.PipelineEvents = gitlab.Bool(d.Get("pipeline_events").(bool)) + opts.PipelineChannel = gitlab.String(d.Get("pipeline_channel").(string)) + opts.WikiPageEvents = gitlab.Bool(d.Get("wiki_page_events").(bool)) + opts.WikiPageChannel = gitlab.String(d.Get("wiki_page_channel").(string)) _, err := client.Services.SetSlackService(project, opts) if err != nil { diff --git a/gitlab/resource_gitlab_service_slack_test.go b/gitlab/resource_gitlab_service_slack_test.go index 505bd4721..2bb3ff0ef 100644 --- a/gitlab/resource_gitlab_service_slack_test.go +++ b/gitlab/resource_gitlab_service_slack_test.go @@ -50,7 +50,7 @@ func TestAccGitlabServiceSlack_basic(t *testing.T) { resource.TestCheckResourceAttr(slackResourceName, "notify_only_broken_pipelines", "false"), ), }, - // Update the slack service to get back to initial settings + // Update the slack service to get back to previous settings { Config: testAccGitlabServiceSlackConfig(rInt), Check: resource.ComposeTestCheckFunc( @@ -61,6 +61,15 @@ func TestAccGitlabServiceSlack_basic(t *testing.T) { resource.TestCheckResourceAttr(slackResourceName, "notify_only_broken_pipelines", "true"), ), }, + // Update the slack service to get back to minimal settings + { + Config: testAccGitlabServiceSlackMinimalConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabServiceExists(slackResourceName, &slackService), + resource.TestCheckResourceAttr(slackResourceName, "webhook", "https://test.com"), + resource.TestCheckResourceAttr(slackResourceName, "push_channel", ""), + ), + }, }, }) } From 394822b61e08c2597dc3ed426756b435e9db85b8 Mon Sep 17 00:00:00 2001 From: Jordan Caussat Date: Fri, 8 Mar 2019 19:02:06 +0100 Subject: [PATCH 16/29] Update user datasource: allow searching by id and add attributes --- gitlab/data_source_gitlab_user.go | 214 ++++++++++++++++++++----- gitlab/data_source_gitlab_user_test.go | 103 ++++++++++-- website/docs/d/user.html.markdown | 58 ++++++- 3 files changed, 317 insertions(+), 58 deletions(-) diff --git a/gitlab/data_source_gitlab_user.go b/gitlab/data_source_gitlab_user.go index 1c2d63abd..e6f9731ef 100644 --- a/gitlab/data_source_gitlab_user.go +++ b/gitlab/data_source_gitlab_user.go @@ -13,13 +13,124 @@ func dataSourceGitlabUser() *schema.Resource { return &schema.Resource{ Read: dataSourceGitlabUserRead, Schema: map[string]*schema.Schema{ - "email": { - Type: schema.TypeString, + "user_id": { + Type: schema.TypeInt, + Computed: true, Optional: true, + ConflictsWith: []string{ + "username", + "email", + }, }, "username": { Type: schema.TypeString, + Computed: true, + Optional: true, + ConflictsWith: []string{ + "user_id", + "email", + }, + }, + "email": { + Type: schema.TypeString, + Computed: true, Optional: true, + ConflictsWith: []string{ + "user_id", + "username", + }, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "is_admin": { + Type: schema.TypeBool, + Computed: true, + }, + "can_create_group": { + Type: schema.TypeBool, + Computed: true, + }, + "can_create_project": { + Type: schema.TypeBool, + Computed: true, + }, + "projects_limit": { + Type: schema.TypeInt, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Computed: true, + }, + "external": { + Type: schema.TypeBool, + Computed: true, + }, + "extern_uid": { + Type: schema.TypeString, + Computed: true, + }, + "organization": { + Type: schema.TypeString, + Computed: true, + }, + "two_factor_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "user_provider": { + Type: schema.TypeString, + Computed: true, + }, + "avatar_url": { + Type: schema.TypeString, + Computed: true, + }, + "bio": { + Type: schema.TypeString, + Computed: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + }, + "skype": { + Type: schema.TypeString, + Computed: true, + }, + "linkedin": { + Type: schema.TypeString, + Computed: true, + }, + "twitter": { + Type: schema.TypeString, + Computed: true, + }, + "website_url": { + Type: schema.TypeString, + Computed: true, + }, + "theme_id": { + Type: schema.TypeInt, + Computed: true, + }, + "color_scheme_id": { + Type: schema.TypeInt, + Computed: true, + }, + "last_sign_in_at": { + Type: schema.TypeString, + Computed: true, + }, + "current_sign_in_at": { + Type: schema.TypeString, + Computed: true, }, }, } @@ -28,48 +139,77 @@ func dataSourceGitlabUser() *schema.Resource { func dataSourceGitlabUserRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*gitlab.Client) + var user *gitlab.User + var err error + log.Printf("[INFO] Reading Gitlab user") - searchEmail := strings.ToLower(d.Get("email").(string)) - userName := strings.ToLower(d.Get("username").(string)) - var q *string - if searchEmail != "" { - q = &searchEmail - } else { - q = &userName - } - query := &gitlab.ListUsersOptions{ - Search: q, - } - users, _, err := client.Users.ListUsers(query) - if err != nil { - return err - } + userIDData, userIDOk := d.GetOk("user_id") + usernameData, usernameOk := d.GetOk("username") + emailData, emailOk := d.GetOk("email") - var found *gitlab.User + if userIDOk { + // Get user by id + user, _, err = client.Users.GetUser(userIDData.(int)) + if err != nil { + return err + } + } else if usernameOk || emailOk { + username := strings.ToLower(usernameData.(string)) + email := strings.ToLower(emailData.(string)) - if searchEmail != "" { - for _, user := range users { - if strings.ToLower(user.Email) == searchEmail { - found = user - break - } + listUsersOptions := &gitlab.ListUsersOptions{} + if usernameOk { + // Get user by username + listUsersOptions.Username = gitlab.String(username) + } else { + // Get user by email + listUsersOptions.Search = gitlab.String(email) } - } else { - for _, user := range users { - if strings.ToLower(user.Username) == userName { - found = user - break - } + + var users []*gitlab.User + users, _, err = client.Users.ListUsers(listUsersOptions) + if err != nil { + return err + } + + if len(users) == 0 { + return fmt.Errorf("couldn't find a user matching: %s%s", username, email) + } else if len(users) != 1 { + return fmt.Errorf("more than one user found matching: %s%s", username, email) } - } - if found == nil { - return fmt.Errorf("The email '%s' does not match any user email", searchEmail) + user = users[0] + } else { + return fmt.Errorf("one and only one of user_id, username or email must be set") } - d.SetId(fmt.Sprintf("%d", found.ID)) - d.Set("name", found.Name) - d.Set("username", found.Username) - d.Set("email", found.Email) + + d.Set("user_id", user.ID) + d.Set("username", user.Username) + d.Set("email", user.Email) + d.Set("name", user.Name) + d.Set("is_admin", user.IsAdmin) + d.Set("can_create_group", user.CanCreateGroup) + d.Set("can_create_project", user.CanCreateProject) + d.Set("projects_limit", user.ProjectsLimit) + d.Set("state", user.State) + d.Set("external", user.External) + d.Set("extern_uid", user.ExternUID) + d.Set("created_at", user.CreatedAt) + d.Set("organization", user.Organization) + d.Set("two_factor_enabled", user.TwoFactorEnabled) + d.Set("provider", user.Provider) + d.Set("avatar_url", user.AvatarURL) + d.Set("bio", user.Bio) + d.Set("location", user.Location) + d.Set("skype", user.Skype) + d.Set("linkedin", user.Linkedin) + d.Set("twitter", user.Twitter) + d.Set("website_url", user.WebsiteURL) + d.Set("theme_id", user.ThemeID) + d.Set("color_scheme_id", user.ColorSchemeID) + + d.SetId(fmt.Sprintf("%d", user.ID)) + return nil } diff --git a/gitlab/data_source_gitlab_user_test.go b/gitlab/data_source_gitlab_user_test.go index 5abd48070..b4fcb4141 100644 --- a/gitlab/data_source_gitlab_user_test.go +++ b/gitlab/data_source_gitlab_user_test.go @@ -9,15 +9,30 @@ import ( "github.com/hashicorp/terraform/terraform" ) -func TestAccDataGitlabUser_basic(t *testing.T) { - userEmail := fmt.Sprintf("tf-%s", acctest.RandString(5)) +func TestAccDataSourceGitlabUser_basic(t *testing.T) { + rString := fmt.Sprintf("%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ + // Get user using its email { - Config: testAccDataGitlabUserConfig(userEmail), + Config: testAccDataGitlabUserConfigEmail(rString), + Check: resource.ComposeTestCheckFunc( + testAccDataSourceGitlabUser("gitlab_user.foo", "data.gitlab_user.foo"), + ), + }, + // Get user using its ID + { + Config: testAccDataGitlabUserConfigUserID(rString), + Check: resource.ComposeTestCheckFunc( + testAccDataSourceGitlabUser("gitlab_user.foo2", "data.gitlab_user.foo2"), + ), + }, + // Get user using its username + { + Config: testAccDataGitlabUserConfigUsername(rString), Check: resource.ComposeTestCheckFunc( testAccDataSourceGitlabUser("gitlab_user.foo", "data.gitlab_user.foo"), ), @@ -35,32 +50,90 @@ func testAccDataSourceGitlabUser(src, n string) resource.TestCheckFunc { search := s.RootModule().Resources[n] searchResource := search.Primary.Attributes - if searchResource["email"] == "" { - return fmt.Errorf("Expected to get user email from Gitlab") + testAttributes := []string{ + "username", + "email", + "name", + "is_admin", + "can_create_group", + "projects_limit", } - testAttributes := []string{"email"} - for _, attribute := range testAttributes { if searchResource[attribute] != userResource[attribute] { - return fmt.Errorf("Expected the user %s to be: %s, but got: %s", attribute, userResource[attribute], searchResource[attribute]) + return fmt.Errorf("Expected user's parameter `%s` to be: %s, but got: `%s`", attribute, userResource[attribute], searchResource[attribute]) } } + return nil } } -func testAccDataGitlabUserConfig(userEmail string) string { +func testAccDataGitlabUserConfigEmail(rString string) string { + return fmt.Sprintf(` +resource "gitlab_user" "foo" { + name = "foo%s" + username = "listest%s" + password = "test%stt" + email = "listest%s@ssss.com" + is_admin = false +} + +resource "gitlab_user" "foo2" { + name = "foo2%s" + username = "listest2%s" + password = "test2%stt" + email = "listest2%s@ssss.com" +} + +data "gitlab_user" "foo" { + email = "${gitlab_user.foo.email}" +} +`, rString, rString, rString, rString, rString, rString, rString, rString) +} + +func testAccDataGitlabUserConfigUserID(rString string) string { + return fmt.Sprintf(` +resource "gitlab_user" "foo" { + name = "foo%s" + username = "listest%s" + password = "test%stt" + email = "listest%s@ssss.com" + is_admin = false +} + +resource "gitlab_user" "foo2" { + name = "foo2%s" + username = "listest2%s" + password = "test2%stt" + email = "listest2%s@ssss.com" +} + +data "gitlab_user" "foo2" { + user_id = "${gitlab_user.foo2.id}" +} +`, rString, rString, rString, rString, rString, rString, rString, rString) +} + +func testAccDataGitlabUserConfigUsername(rString string) string { return fmt.Sprintf(` resource "gitlab_user" "foo" { - name = "foo %s" - username = "listest%s" - password = "test%stt" - email = "listest%s@ssss.com" + name = "foo%s" + username = "listest%s" + password = "test%stt" + email = "listest%s@ssss.com" + is_admin = false +} + +resource "gitlab_user" "foo2" { + name = "foo2%s" + username = "listest2%s" + password = "test2%stt" + email = "listest2%s@ssss.com" } data "gitlab_user" "foo" { - email = "${gitlab_user.foo.email}" + username = "${gitlab_user.foo.username}" } - `, userEmail, userEmail, userEmail, userEmail) +`, rString, rString, rString, rString, rString, rString, rString, rString) } diff --git a/website/docs/d/user.html.markdown b/website/docs/d/user.html.markdown index 45d5a790d..73c9718b9 100644 --- a/website/docs/d/user.html.markdown +++ b/website/docs/d/user.html.markdown @@ -14,7 +14,7 @@ Provides details about a specific user in the gitlab provider. Especially the ab ```hcl data "gitlab_user" "example" { - email = "test@aaa.com" + username = "myuser" } ``` @@ -26,18 +26,64 @@ The following arguments are supported: * `username` - (Optional) The username of the user. -If both are given only e-mail is used. +* `user_id` - (Optional) The ID of the user. -## Attributes Reference +**Note**: only one of email, user_id or username must be provided. -The following attributes are exported: +## Attributes Reference -* `name` - The name of the user. +* `id` - The unique id assigned to the user by the gitlab server. * `username` - The username of the user. * `email` - The e-mail address of the user. -* `id` - The unique id assigned to the user by the gitlab server. +* `name` - The name of the user. + +* `is_admin` - Whether the user is an admin. + +* `can_create_group` - Whether the user can create groups. + +* `can_create_project` - Whether the user can create projects. + +* `projects_limit` - Number of projects the user can create. + +* `created_at` - Date the user was created at. + +* `state` - Whether the user is active or blocked. + +* `external` - Whether the user is external. + +* `extern_uid` - The external UID of the user. + +* `user_provider` - The UID provider of the user. + +* `organization` - The organization of the user. + +* `two_factor_enabled` - Whether user's two factor auth is enabled. + +* `avatar_url` - The avatar URL of the user. + +* `bio` - The bio of the user. + +* `location` - The location of the user. + +* `skype` - Skype username of the user. + +* `linkedin` - Linkedin profile of the user. + +* `twitter` - Twitter username of the user. + +* `website_url` - User's website URL. + +* `theme_id` - User's theme ID. + +* `color_scheme_id` - User's color scheme ID. + +* `last_sign_in_at` - Last user's sign-in date. + +* `current_sign_in_at` - Current user's sign-in date. +**Note**: some attributes might not be returned depending on if you're an admin or not. Please refer to [doc][doc] for more details. +[doc]: https://docs.gitlab.com/ce/api/users.html#single-user \ No newline at end of file From 51afe1e427cd04719618494b7da79242d5351b66 Mon Sep 17 00:00:00 2001 From: Nick Fagerlund Date: Thu, 21 Mar 2019 17:39:39 -0700 Subject: [PATCH 17/29] website: make example server URL non-clickable The site's markdown processor tries to automatically turn URLs into links, but this one doesn't go anywhere, so let's style it as a code span. --- website/docs/index.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index b68ff8f98..4afda084d 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -69,7 +69,7 @@ The following arguments are supported in the `provider` block: it can also be sourced from the `GITLAB_TOKEN` environment variable. * `base_url` - (Optional) This is the target GitLab base API endpoint. Providing a value is a - requirement when working with GitLab CE or GitLab Enterprise e.g. https://my.gitlab.server/api/v4/. + requirement when working with GitLab CE or GitLab Enterprise e.g. `https://my.gitlab.server/api/v4/`. It is optional to provide this value and it can also be sourced from the `GITLAB_BASE_URL` environment variable. The value must end with a slash. From 149b695a3406f3befae80390a5ac4c221b982b2b Mon Sep 17 00:00:00 2001 From: Matej Velikonja Date: Mon, 25 Mar 2019 13:27:17 +0100 Subject: [PATCH 18/29] fix project cluster acc test by adding a fake pem certificate --- .../resource_gitlab_project_cluster_test.go | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/gitlab/resource_gitlab_project_cluster_test.go b/gitlab/resource_gitlab_project_cluster_test.go index 4c7ff6328..5df8e2faa 100644 --- a/gitlab/resource_gitlab_project_cluster_test.go +++ b/gitlab/resource_gitlab_project_cluster_test.go @@ -28,6 +28,7 @@ func TestAccGitlabProjectCluster_basic(t *testing.T) { Name: fmt.Sprintf("foo-cluster-%d", rInt), EnvironmentScope: "*", KubernetesApiURL: "https://123.123.123", + KubernetesCACert: projectClusterFakeCert, KubernetesAuthorizationType: "abac", }), ), @@ -41,7 +42,7 @@ func TestAccGitlabProjectCluster_basic(t *testing.T) { Name: fmt.Sprintf("foo-cluster-%d", rInt), EnvironmentScope: "*", KubernetesApiURL: "https://124.124.124", - KubernetesCACert: "some-cert", + KubernetesCACert: projectClusterFakeCert, KubernetesNamespace: "changed-namespace", KubernetesAuthorizationType: "abac", }), @@ -56,7 +57,7 @@ func TestAccGitlabProjectCluster_basic(t *testing.T) { Name: fmt.Sprintf("foo-cluster-%d", rInt), EnvironmentScope: "*", KubernetesApiURL: "https://124.124.124", - KubernetesCACert: "some-cert", + KubernetesCACert: projectClusterFakeCert, KubernetesNamespace: "changed-namespace", KubernetesAuthorizationType: "rbac", }), @@ -180,6 +181,12 @@ func testAccCheckGitlabProjectClusterAttributes(cluster *gitlab.ProjectCluster, func testAccGitlabProjectClusterConfig(rInt int) string { return fmt.Sprintf(` +variable "cert" { + default = < Date: Thu, 28 Mar 2019 13:37:28 +0000 Subject: [PATCH 19/29] Update project_variable.html.markdown --- website/docs/r/project_variable.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/project_variable.html.markdown b/website/docs/r/project_variable.html.markdown index 45e6e261d..ada3dfe08 100644 --- a/website/docs/r/project_variable.html.markdown +++ b/website/docs/r/project_variable.html.markdown @@ -41,5 +41,5 @@ The following arguments are supported: GitLab project variables can be imported using an id made up of `projectid:variablename`, e.g. ``` -$ terraform import gitlab_group_membership.test 12345:project_variable_key -``` \ No newline at end of file +$ terraform import gitlab_project_variable.example 12345:project_variable_key +``` From e5a9d5158d11dd9a605d2f6b3ddfbe0df7451795 Mon Sep 17 00:00:00 2001 From: xM8WVqaG <44505331+xM8WVqaG@users.noreply.github.com> Date: Thu, 28 Mar 2019 15:01:32 +0000 Subject: [PATCH 20/29] Update group_variable.html.markdown --- website/docs/r/group_variable.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/group_variable.html.markdown b/website/docs/r/group_variable.html.markdown index 23424e4ac..b23c612f6 100644 --- a/website/docs/r/group_variable.html.markdown +++ b/website/docs/r/group_variable.html.markdown @@ -41,5 +41,5 @@ The following arguments are supported: GitLab group variables can be imported using an id made up of `groupid:variablename`, e.g. ``` -$ terraform import gitlab_group_membership.test 12345:group_variable_key -``` \ No newline at end of file +$ terraform import gitlab_group_variable.example 12345:group_variable_key +``` From 07f58868d679eeee7f6c5ddf6873adc9fc9d41f4 Mon Sep 17 00:00:00 2001 From: xM8WVqaG <44505331+xM8WVqaG@users.noreply.github.com> Date: Thu, 28 Mar 2019 15:02:04 +0000 Subject: [PATCH 21/29] Update project_membership.html.markdown --- website/docs/r/project_membership.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/project_membership.html.markdown b/website/docs/r/project_membership.html.markdown index 26b226289..285315c2b 100644 --- a/website/docs/r/project_membership.html.markdown +++ b/website/docs/r/project_membership.html.markdown @@ -35,4 +35,4 @@ The following arguments are supported: GitLab group membership can be imported using an id made up of `groupid:username`, e.g. ``` -$ terraform import gitlab_group_membership.test 12345:1337 \ No newline at end of file +$ terraform import gitlab_project_membership.test 12345:1337 From 7009bcd01a71408d76a206eec565a2a3ff6379d8 Mon Sep 17 00:00:00 2001 From: Martin Fernandez Date: Wed, 10 Apr 2019 11:51:19 -0300 Subject: [PATCH 22/29] Bump go-gitlab to v0.16.1 --- gitlab/data_source_gitlab_project.go | 2 +- gitlab/resource_gitlab_label_test.go | 2 +- .../resource_gitlab_pipeline_trigger_test.go | 2 +- gitlab/resource_gitlab_project.go | 6 +- gitlab/resource_gitlab_project_hook_test.go | 2 +- gitlab/resource_gitlab_project_test.go | 4 +- .../resource_gitlab_project_variable_test.go | 2 +- go.mod | 2 +- go.sum | 2 + vendor/github.com/xanzy/go-gitlab/README.md | 1 + vendor/github.com/xanzy/go-gitlab/gitlab.go | 10 + vendor/github.com/xanzy/go-gitlab/go.mod | 1 + vendor/github.com/xanzy/go-gitlab/go.sum | 7 + .../xanzy/go-gitlab/group_badges.go | 214 +++++++++++++++++ .../xanzy/go-gitlab/group_labels.go | 197 ++++++++++++++++ .../xanzy/go-gitlab/merge_requests.go | 3 + .../github.com/xanzy/go-gitlab/pipelines.go | 1 + vendor/github.com/xanzy/go-gitlab/projects.go | 20 +- vendor/github.com/xanzy/go-gitlab/registry.go | 220 ++++++++++++++++++ .../xanzy/go-gitlab/releaselinks.go | 177 ++++++++++++++ vendor/github.com/xanzy/go-gitlab/releases.go | 213 +++++++++++++++++ vendor/github.com/xanzy/go-gitlab/runners.go | 19 +- vendor/github.com/xanzy/go-gitlab/tags.go | 45 ++-- vendor/github.com/xanzy/go-gitlab/todos.go | 2 +- vendor/github.com/xanzy/go-gitlab/users.go | 19 +- vendor/modules.txt | 2 +- 26 files changed, 1124 insertions(+), 51 deletions(-) create mode 100644 vendor/github.com/xanzy/go-gitlab/group_badges.go create mode 100644 vendor/github.com/xanzy/go-gitlab/group_labels.go create mode 100644 vendor/github.com/xanzy/go-gitlab/registry.go create mode 100644 vendor/github.com/xanzy/go-gitlab/releaselinks.go create mode 100644 vendor/github.com/xanzy/go-gitlab/releases.go diff --git a/gitlab/data_source_gitlab_project.go b/gitlab/data_source_gitlab_project.go index 4f89a0413..9434f4188 100644 --- a/gitlab/data_source_gitlab_project.go +++ b/gitlab/data_source_gitlab_project.go @@ -98,7 +98,7 @@ func dataSourceGitlabProjectRead(d *schema.ResourceData, meta interface{}) error v, _ := d.GetOk("id") - found, _, err := client.Projects.GetProject(v) + found, _, err := client.Projects.GetProject(v, nil) if err != nil { return err } diff --git a/gitlab/resource_gitlab_label_test.go b/gitlab/resource_gitlab_label_test.go index 60eefaae9..f4381df77 100644 --- a/gitlab/resource_gitlab_label_test.go +++ b/gitlab/resource_gitlab_label_test.go @@ -119,7 +119,7 @@ func testAccCheckGitlabLabelDestroy(s *terraform.State) error { continue } - gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil) if err == nil { if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { return fmt.Errorf("Repository still exists") diff --git a/gitlab/resource_gitlab_pipeline_trigger_test.go b/gitlab/resource_gitlab_pipeline_trigger_test.go index 0ef41aff2..42273f61d 100644 --- a/gitlab/resource_gitlab_pipeline_trigger_test.go +++ b/gitlab/resource_gitlab_pipeline_trigger_test.go @@ -104,7 +104,7 @@ func testAccCheckGitlabPipelineTriggerDestroy(s *terraform.State) error { continue } - gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil) if err == nil { if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { return fmt.Errorf("Repository still exists") diff --git a/gitlab/resource_gitlab_project.go b/gitlab/resource_gitlab_project.go index 9e16b885c..2ee452ab3 100644 --- a/gitlab/resource_gitlab_project.go +++ b/gitlab/resource_gitlab_project.go @@ -216,7 +216,7 @@ func resourceGitlabProjectRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*gitlab.Client) log.Printf("[DEBUG] read gitlab project %s", d.Id()) - project, response, err := client.Projects.GetProject(d.Id()) + project, response, err := client.Projects.GetProject(d.Id(), nil) if err != nil { if response.StatusCode == 404 { log.Printf("[WARN] removing project %s from state because it no longer exists in gitlab", d.Id()) @@ -318,7 +318,7 @@ func resourceGitlabProjectDelete(d *schema.ResourceData, meta interface{}) error Pending: []string{"Deleting"}, Target: []string{"Deleted"}, Refresh: func() (interface{}, string, error) { - out, response, err := client.Projects.GetProject(d.Id()) + out, response, err := client.Projects.GetProject(d.Id(), nil) if err != nil { if response.StatusCode == 404 { return out, "Deleted", nil @@ -412,7 +412,7 @@ func updateSharedWithGroups(d *schema.ResourceData, meta interface{}) error { // Get target groups from the TF config and current groups from Gitlab server targetGroups := expandSharedWithGroupsOptions(d.Get("shared_with_groups")) - project, _, err := client.Projects.GetProject(d.Id()) + project, _, err := client.Projects.GetProject(d.Id(), nil) if err != nil { return err } diff --git a/gitlab/resource_gitlab_project_hook_test.go b/gitlab/resource_gitlab_project_hook_test.go index e8e23d0db..2ea96fda7 100644 --- a/gitlab/resource_gitlab_project_hook_test.go +++ b/gitlab/resource_gitlab_project_hook_test.go @@ -160,7 +160,7 @@ func testAccCheckGitlabProjectHookDestroy(s *terraform.State) error { continue } - gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil) if err == nil { if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { return fmt.Errorf("Repository still exists") diff --git a/gitlab/resource_gitlab_project_test.go b/gitlab/resource_gitlab_project_test.go index 0086120df..70a041d69 100644 --- a/gitlab/resource_gitlab_project_test.go +++ b/gitlab/resource_gitlab_project_test.go @@ -210,7 +210,7 @@ func testAccCheckGitlabProjectExists(n string, project *gitlab.Project) resource } conn := testAccProvider.Meta().(*gitlab.Client) - gotProject, _, err := conn.Projects.GetProject(repoName) + gotProject, _, err := conn.Projects.GetProject(repoName, nil) if err != nil { return err } @@ -317,7 +317,7 @@ func testAccCheckGitlabProjectDestroy(s *terraform.State) error { continue } - gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil) if err == nil { if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { return fmt.Errorf("Repository still exists") diff --git a/gitlab/resource_gitlab_project_variable_test.go b/gitlab/resource_gitlab_project_variable_test.go index 171ea4521..dad2cf143 100644 --- a/gitlab/resource_gitlab_project_variable_test.go +++ b/gitlab/resource_gitlab_project_variable_test.go @@ -116,7 +116,7 @@ func testAccCheckGitlabProjectVariableDestroy(s *terraform.State) error { continue } - gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil) if err == nil { if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { return fmt.Errorf("Repository still exists") diff --git a/go.mod b/go.mod index 28612e802..2f9ab5d6d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,6 @@ require ( github.com/blang/semver v3.5.1+incompatible // indirect github.com/hashicorp/terraform v0.11.12-beta1.0.20190227065421-fc531f54a878 github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa // indirect - github.com/xanzy/go-gitlab v0.14.1 + github.com/xanzy/go-gitlab v0.16.1 golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e // indirect ) diff --git a/go.sum b/go.sum index f7851d5dc..b7ca3d511 100644 --- a/go.sum +++ b/go.sum @@ -243,6 +243,8 @@ github.com/ulikunitz/xz v0.5.4 h1:zATC2OoZ8H1TZll3FpbX+ikwmadbO699PE06cIkm9oU= github.com/ulikunitz/xz v0.5.4/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/xanzy/go-gitlab v0.14.1 h1:+CipI8+oQxqWNmKCU/9GQvlQnJ5v366ChHNEI4O83is= github.com/xanzy/go-gitlab v0.14.1/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/go-gitlab v0.16.1 h1:kRHZ/wDsMkJHJvzfielqBTTrsbCtoxeEFrwiwtvVbZw= +github.com/xanzy/go-gitlab v0.16.1/go.mod h1:LSfUQ9OPDnwRqulJk2HcWaAiFfCzaknyeGvjQI67MbE= github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro= github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= diff --git a/vendor/github.com/xanzy/go-gitlab/README.md b/vendor/github.com/xanzy/go-gitlab/README.md index fb03398e6..bb5239dd4 100644 --- a/vendor/github.com/xanzy/go-gitlab/README.md +++ b/vendor/github.com/xanzy/go-gitlab/README.md @@ -29,6 +29,7 @@ to add new and/or missing endpoints. Currently the following services are suppor - [x] Branches - [x] Broadcast Messages - [x] Commits +- [x] Container Registry - [x] Custom Attributes - [x] Deploy Keys - [x] Deployments diff --git a/vendor/github.com/xanzy/go-gitlab/gitlab.go b/vendor/github.com/xanzy/go-gitlab/gitlab.go index a3da78b52..ec9cdcf0b 100644 --- a/vendor/github.com/xanzy/go-gitlab/gitlab.go +++ b/vendor/github.com/xanzy/go-gitlab/gitlab.go @@ -294,6 +294,7 @@ type Client struct { BuildVariables *BuildVariablesService CIYMLTemplate *CIYMLTemplatesService Commits *CommitsService + ContainerRegistry *ContainerRegistryService CustomAttribute *CustomAttributesService DeployKeys *DeployKeysService Deployments *DeploymentsService @@ -302,7 +303,9 @@ type Client struct { Events *EventsService Features *FeaturesService GitIgnoreTemplates *GitIgnoreTemplatesService + GroupBadges *GroupBadgesService GroupIssueBoards *GroupIssueBoardsService + GroupLabels *GroupLabelsService GroupMembers *GroupMembersService GroupMilestones *GroupMilestonesService GroupVariables *GroupVariablesService @@ -332,6 +335,8 @@ type Client struct { Projects *ProjectsService ProtectedBranches *ProtectedBranchesService ProtectedTags *ProtectedTagsService + ReleaseLinks *ReleaseLinksService + Releases *ReleasesService Repositories *RepositoriesService RepositoryFiles *RepositoryFilesService Runners *RunnersService @@ -436,6 +441,7 @@ func newClient(httpClient *http.Client) *Client { c.BuildVariables = &BuildVariablesService{client: c} c.CIYMLTemplate = &CIYMLTemplatesService{client: c} c.Commits = &CommitsService{client: c} + c.ContainerRegistry = &ContainerRegistryService{client: c} c.CustomAttribute = &CustomAttributesService{client: c} c.DeployKeys = &DeployKeysService{client: c} c.Deployments = &DeploymentsService{client: c} @@ -444,7 +450,9 @@ func newClient(httpClient *http.Client) *Client { c.Events = &EventsService{client: c} c.Features = &FeaturesService{client: c} c.GitIgnoreTemplates = &GitIgnoreTemplatesService{client: c} + c.GroupBadges = &GroupBadgesService{client: c} c.GroupIssueBoards = &GroupIssueBoardsService{client: c} + c.GroupLabels = &GroupLabelsService{client: c} c.GroupMembers = &GroupMembersService{client: c} c.GroupMilestones = &GroupMilestonesService{client: c} c.GroupVariables = &GroupVariablesService{client: c} @@ -474,6 +482,8 @@ func newClient(httpClient *http.Client) *Client { c.Projects = &ProjectsService{client: c} c.ProtectedBranches = &ProtectedBranchesService{client: c} c.ProtectedTags = &ProtectedTagsService{client: c} + c.ReleaseLinks = &ReleaseLinksService{client: c} + c.Releases = &ReleasesService{client: c} c.Repositories = &RepositoriesService{client: c} c.RepositoryFiles = &RepositoryFilesService{client: c} c.Runners = &RunnersService{client: c} diff --git a/vendor/github.com/xanzy/go-gitlab/go.mod b/vendor/github.com/xanzy/go-gitlab/go.mod index 384005564..c74a1d6dc 100644 --- a/vendor/github.com/xanzy/go-gitlab/go.mod +++ b/vendor/github.com/xanzy/go-gitlab/go.mod @@ -2,6 +2,7 @@ module github.com/xanzy/go-gitlab require ( github.com/google/go-querystring v1.0.0 + github.com/stretchr/testify v1.3.0 golang.org/x/net v0.0.0-20181108082009-03003ca0c849 // indirect golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect diff --git a/vendor/github.com/xanzy/go-gitlab/go.sum b/vendor/github.com/xanzy/go-gitlab/go.sum index 2916d94ba..ef4a85ee4 100644 --- a/vendor/github.com/xanzy/go-gitlab/go.sum +++ b/vendor/github.com/xanzy/go-gitlab/go.sum @@ -1,7 +1,14 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181108082009-03003ca0c849 h1:FSqE2GGG7wzsYUsWiQ8MZrvEd1EOyU3NCF0AW3Wtltg= golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/vendor/github.com/xanzy/go-gitlab/group_badges.go b/vendor/github.com/xanzy/go-gitlab/group_badges.go new file mode 100644 index 000000000..61981a61f --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/group_badges.go @@ -0,0 +1,214 @@ +package gitlab + +import ( + "fmt" + "net/url" +) + +// GroupBadgesService handles communication with the group badges +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html +type GroupBadgesService struct { + client *Client +} + +// BadgeKind represents a GitLab Badge Kind +type BadgeKind string + +// all possible values Badge Kind +const ( + ProjectBadgeKind BadgeKind = "project" + GroupBadgeKind BadgeKind = "group" +) + +// GroupBadge represents a group badge. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html +type GroupBadge struct { + ID int `json:"id"` + LinkURL string `json:"link_url"` + ImageURL string `json:"image_url"` + RenderedLinkURL string `json:"rendered_link_url"` + RenderedImageURL string `json:"rendered_image_url"` + Kind BadgeKind `json:"kind"` +} + +// ListGroupBadgesOptions represents the available ListGroupBadges() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#list-all-badges-of-a-group +type ListGroupBadgesOptions ListOptions + +// ListGroupBadges gets a list of a group badges. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#list-all-badges-of-a-group +func (s *GroupBadgesService) ListGroupBadges(gid interface{}, opt *ListGroupBadgesOptions, options ...OptionFunc) ([]*GroupBadge, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/badges", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var gb []*GroupBadge + resp, err := s.client.Do(req, &gb) + if err != nil { + return nil, resp, err + } + + return gb, resp, err +} + +// GetGroupBadge gets a group badge. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#get-a-badge-of-a-group +func (s *GroupBadgesService) GetGroupBadge(gid interface{}, badge int, options ...OptionFunc) (*GroupBadge, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/badges/%d", url.QueryEscape(group), badge) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + gb := new(GroupBadge) + resp, err := s.client.Do(req, gb) + if err != nil { + return nil, resp, err + } + + return gb, resp, err +} + +// AddGroupBadgeOptions represents the available AddGroupBadge() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#add-a-badge-to-a-group +type AddGroupBadgeOptions struct { + LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"` + ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"` +} + +// AddGroupBadge adds a badge to a group. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#add-a-badge-to-a-group +func (s *GroupBadgesService) AddGroupBadge(gid interface{}, opt *AddGroupBadgeOptions, options ...OptionFunc) (*GroupBadge, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/badges", url.QueryEscape(group)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + gb := new(GroupBadge) + resp, err := s.client.Do(req, gb) + if err != nil { + return nil, resp, err + } + + return gb, resp, err +} + +// EditGroupBadgeOptions represents the available EditGroupBadge() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#edit-a-badge-of-a-group +type EditGroupBadgeOptions struct { + LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"` + ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"` +} + +// EditGroupBadge updates a badge of a group. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#edit-a-badge-of-a-group +func (s *GroupBadgesService) EditGroupBadge(gid interface{}, badge int, opt *EditGroupBadgeOptions, options ...OptionFunc) (*GroupBadge, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/badges/%d", url.QueryEscape(group), badge) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + gb := new(GroupBadge) + resp, err := s.client.Do(req, gb) + if err != nil { + return nil, resp, err + } + + return gb, resp, err +} + +// DeleteGroupBadge removes a badge from a group. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#remove-a-badge-from-a-group +func (s *GroupBadgesService) DeleteGroupBadge(gid interface{}, badge int, options ...OptionFunc) (*Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s/badges/%d", url.QueryEscape(group), badge) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// GroupBadgePreviewOptions represents the available PreviewGroupBadge() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#preview-a-badge-from-a-group +type GroupBadgePreviewOptions struct { + LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"` + ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"` +} + +// PreviewGroupBadge returns how the link_url and image_url final URLs would be after +// resolving the placeholder interpolation. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_badges.html#preview-a-badge-from-a-group +func (s *GroupBadgesService) PreviewGroupBadge(gid interface{}, opt *GroupBadgePreviewOptions, options ...OptionFunc) (*GroupBadge, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/badges/render", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + gb := new(GroupBadge) + resp, err := s.client.Do(req, &gb) + if err != nil { + return nil, resp, err + } + + return gb, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/group_labels.go b/vendor/github.com/xanzy/go-gitlab/group_labels.go new file mode 100644 index 000000000..c429817f5 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/group_labels.go @@ -0,0 +1,197 @@ +package gitlab + +import ( + "fmt" + "net/url" +) + +// GroupLabelsService handles communication with the label related methods of the +// GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/group_labels.html +type GroupLabelsService struct { + client *Client +} + +// GroupLabel represents a GitLab group label. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/group_labels.html +type GroupLabel Label + +func (l GroupLabel) String() string { + return Stringify(l) +} + +// ListGroupLabelsOptions represents the available ListGroupLabels() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#list-labels +type ListGroupLabelsOptions ListOptions + +// ListGroupLabels gets all labels for given group. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#list-group-labels +func (s *GroupLabelsService) ListGroupLabels(gid interface{}, opt *ListGroupLabelsOptions, options ...OptionFunc) ([]*GroupLabel, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/labels", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var l []*GroupLabel + resp, err := s.client.Do(req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// CreateGroupLabelOptions represents the available CreateGroupLabel() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#create-a-new-group-label +type CreateGroupLabelOptions CreateLabelOptions + +// CreateGroupLabel creates a new label for given group with given name and +// color. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#create-a-new-group-label +func (s *GroupLabelsService) CreateGroupLabel(gid interface{}, opt *CreateGroupLabelOptions, options ...OptionFunc) (*GroupLabel, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/labels", url.QueryEscape(group)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + l := new(GroupLabel) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// DeleteGroupLabelOptions represents the available DeleteGroupLabel() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#delete-a-group-label +type DeleteGroupLabelOptions DeleteLabelOptions + +// DeleteGroupLabel deletes a group label given by its name. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#delete-a-label +func (s *GroupLabelsService) DeleteGroupLabel(gid interface{}, opt *DeleteGroupLabelOptions, options ...OptionFunc) (*Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s/labels", url.QueryEscape(group)) + + req, err := s.client.NewRequest("DELETE", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// UpdateGroupLabelOptions represents the available UpdateGroupLabel() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#update-a-group-label +type UpdateGroupLabelOptions UpdateLabelOptions + +// UpdateGroupLabel updates an existing label with new name or now color. At least +// one parameter is required, to update the label. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#update-a-group-label +func (s *GroupLabelsService) UpdateGroupLabel(gid interface{}, opt *UpdateGroupLabelOptions, options ...OptionFunc) (*GroupLabel, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/labels", url.QueryEscape(group)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + l := new(GroupLabel) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// SubscribeToGroupLabel subscribes the authenticated user to a label to receive +// notifications. If the user is already subscribed to the label, the status +// code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#subscribe-to-a-group-label +func (s *GroupLabelsService) SubscribeToGroupLabel(gid interface{}, labelID interface{}, options ...OptionFunc) (*GroupLabel, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + label, err := parseID(labelID) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/labels/%s/subscribe", url.QueryEscape(group), label) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + l := new(GroupLabel) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// UnsubscribeFromGroupLabel unsubscribes the authenticated user from a label to not +// receive notifications from it. If the user is not subscribed to the label, the +// status code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_labels.html#unsubscribe-from-a-group-label +func (s *GroupLabelsService) UnsubscribeFromGroupLabel(gid interface{}, labelID interface{}, options ...OptionFunc) (*Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, err + } + label, err := parseID(labelID) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s/labels/%s/unsubscribe", url.QueryEscape(group), label) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/merge_requests.go b/vendor/github.com/xanzy/go-gitlab/merge_requests.go index 23633f6bb..2b9dd6389 100644 --- a/vendor/github.com/xanzy/go-gitlab/merge_requests.go +++ b/vendor/github.com/xanzy/go-gitlab/merge_requests.go @@ -169,6 +169,8 @@ type ListMergeRequestsOptions struct { SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"` TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` + In *string `url:"in,omitempty" json:"in,omitempty"` + WIP *string `url:"wip,omitempty" json:"wip,omitempty"` } // ListMergeRequests gets all merge requests. The state parameter can be used @@ -269,6 +271,7 @@ type ListProjectMergeRequestsOptions struct { SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"` TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` + WIP *string `url:"wip,omitempty" json:"wip,omitempty"` } // ListProjectMergeRequests gets all merge requests for this project. diff --git a/vendor/github.com/xanzy/go-gitlab/pipelines.go b/vendor/github.com/xanzy/go-gitlab/pipelines.go index b2f470f3d..8466eac63 100644 --- a/vendor/github.com/xanzy/go-gitlab/pipelines.go +++ b/vendor/github.com/xanzy/go-gitlab/pipelines.go @@ -64,6 +64,7 @@ type Pipeline struct { CommittedAt *time.Time `json:"committed_at"` Duration int `json:"duration"` Coverage string `json:"coverage"` + WebURL string `json:"web_url"` } func (i Pipeline) String() string { diff --git a/vendor/github.com/xanzy/go-gitlab/projects.go b/vendor/github.com/xanzy/go-gitlab/projects.go index bbd41895c..8834d5d58 100644 --- a/vendor/github.com/xanzy/go-gitlab/projects.go +++ b/vendor/github.com/xanzy/go-gitlab/projects.go @@ -82,6 +82,11 @@ type Project struct { RequestAccessEnabled bool `json:"request_access_enabled"` MergeMethod MergeMethodValue `json:"merge_method"` ForkedFromProject *ForkParent `json:"forked_from_project"` + Mirror bool `json:"mirror"` + MirrorUserID int `json:"mirror_user_id"` + MirrorTriggerBuilds bool `json:"mirror_trigger_builds"` + OnlyMirrorProtectedBranches bool `json:"only_mirror_protected_branches"` + MirrorOverwritesDivergedBranches bool `json:"mirror_overwrites_diverged_branches"` SharedWithGroups []struct { GroupID int `json:"group_id"` GroupName string `json:"group_name"` @@ -315,19 +320,28 @@ func (s *ProjectsService) GetProjectLanguages(pid interface{}, options ...Option return p, resp, err } +// GetProjectOptions represents the available GetProject() options. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#get-single-project +type GetProjectOptions struct { + Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"` + License *bool `url:"license,omitempty" json:"license,omitempty"` + WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"` +} + // GetProject gets a specific project, identified by project ID or // NAMESPACE/PROJECT_NAME, which is owned by the authenticated user. // // GitLab API docs: // https://docs.gitlab.com/ce/api/projects.html#get-single-project -func (s *ProjectsService) GetProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { +func (s *ProjectsService) GetProject(pid interface{}, opt *GetProjectOptions, options ...OptionFunc) (*Project, *Response, error) { project, err := parseID(pid) if err != nil { return nil, nil, err } u := fmt.Sprintf("projects/%s", url.QueryEscape(project)) - req, err := s.client.NewRequest("GET", u, nil, options) + req, err := s.client.NewRequest("GET", u, opt, options) if err != nil { return nil, nil, err } @@ -430,7 +444,7 @@ type CreateProjectOptions struct { TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"` PrintingMergeRequestLinkEnabled *bool `url:"printing_merge_request_link_enabled,omitempty" json:"printing_merge_request_link_enabled,omitempty"` CIConfigPath *string `url:"ci_config_path,omitempty" json:"ci_config_path,omitempty"` - ApprovalsBeforeMerge *int `url:"approvals_before_merge" json:"approvals_before_merge"` + ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` } // CreateProject creates a new project owned by the authenticated user. diff --git a/vendor/github.com/xanzy/go-gitlab/registry.go b/vendor/github.com/xanzy/go-gitlab/registry.go new file mode 100644 index 000000000..d74769de3 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/registry.go @@ -0,0 +1,220 @@ +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// ContainerRegistryService handles communication with the container registry +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/container_registry.html +type ContainerRegistryService struct { + client *Client +} + +// RegistryRepository represents a GitLab content registry repository. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/container_registry.html +type RegistryRepository struct { + ID int `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Location string `json:"location"` + CreatedAt *time.Time `json:"created_at"` +} + +func (s RegistryRepository) String() string { + return Stringify(s) +} + +// RegistryRepositoryTag represents a GitLab registry image tag. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/container_registry.html +type RegistryRepositoryTag struct { + Name string `json:"name"` + Path string `json:"path"` + Location string `json:"location"` + Revision string `json:"revision"` + ShortRevision string `json:"short_revision"` + Digest string `json:"digest"` + CreatedAt *time.Time `json:"created_at"` + TotalSize int `json:"total_size"` +} + +func (s RegistryRepositoryTag) String() string { + return Stringify(s) +} + +// ListRegistryRepositoriesOptions represents the available +// ListRegistryRepositories() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repositories +type ListRegistryRepositoriesOptions ListOptions + +// ListRegistryRepositories gets a list of registry repositories in a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repositories +func (s *ContainerRegistryService) ListRegistryRepositories(pid interface{}, opt *ListRegistryRepositoriesOptions, options ...OptionFunc) ([]*RegistryRepository, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/registry/repositories", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var repos []*RegistryRepository + resp, err := s.client.Do(req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, err +} + +// DeleteRegistryRepository deletes a repository in a registry. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#delete-registry-repository +func (s *ContainerRegistryService) DeleteRegistryRepository(pid interface{}, repository int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/registry/repositories/%d", url.QueryEscape(project), repository) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ListRegistryRepositoryTagsOptions represents the available +// ListRegistryRepositoryTags() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#list-repository-tags +type ListRegistryRepositoryTagsOptions ListOptions + +// ListRegistryRepositoryTags gets a list of tags for given registry repository. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#list-repository-tags +func (s *ContainerRegistryService) ListRegistryRepositoryTags(pid interface{}, repository int, opt *ListRegistryRepositoryTagsOptions, options ...OptionFunc) ([]*RegistryRepositoryTag, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags", + url.QueryEscape(project), + repository, + ) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var tags []*RegistryRepositoryTag + resp, err := s.client.Do(req, &tags) + if err != nil { + return nil, resp, err + } + + return tags, resp, err +} + +// GetRegistryRepositoryTagDetail get details of a registry repository tag +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-repository-tag +func (s *ContainerRegistryService) GetRegistryRepositoryTagDetail(pid interface{}, repository int, tagName string, options ...OptionFunc) (*RegistryRepositoryTag, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags/%s", + url.QueryEscape(project), + repository, + tagName, + ) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + tag := new(RegistryRepositoryTag) + resp, err := s.client.Do(req, &tag) + if err != nil { + return nil, resp, err + } + + return tag, resp, err +} + +// DeleteRegistryRepositoryTag deletes a registry repository tag. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#delete-a-repository-tag +func (s *ContainerRegistryService) DeleteRegistryRepositoryTag(pid interface{}, repository int, tagName string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags/%s", + url.QueryEscape(project), + repository, + tagName, + ) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteRegistryRepositoryTagsOptions represents the available +// DeleteRegistryRepositoryTags() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#delete-repository-tags-in-bulk +type DeleteRegistryRepositoryTagsOptions struct { + NameRegexp *string `url:"name_regex,omitempty" json:"name_regex,omitempty"` + KeepN *int `url:"keep_n,omitempty" json:"keep_n,omitempty"` + OlderThan *string `url:"older_than,omitempty" json:"older_than,omitempty"` +} + +// DeleteRegistryRepositoryTags deletes repository tags in bulk based on +// given criteria. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/container_registry.html#delete-repository-tags-in-bulk +func (s *ContainerRegistryService) DeleteRegistryRepositoryTags(pid interface{}, repository int, opt *DeleteRegistryRepositoryTagsOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags", + url.QueryEscape(project), + repository, + ) + + req, err := s.client.NewRequest("DELETE", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/releaselinks.go b/vendor/github.com/xanzy/go-gitlab/releaselinks.go new file mode 100644 index 000000000..71621e215 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/releaselinks.go @@ -0,0 +1,177 @@ +package gitlab + +import ( + "fmt" + "net/url" +) + +// ReleaseLinksService handles communication with the release link methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html +type ReleaseLinksService struct { + client *Client +} + +// ReleaseLink represents a release link. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html +type ReleaseLink struct { + ID int `json:"id"` + Name string `json:"name"` + URL string `json:"url"` + External bool `json:"external"` +} + +// ListReleaseLinksOptions represents ListReleaseLinks() options. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#get-links +type ListReleaseLinksOptions ListOptions + +// ListReleaseLinks gets assets as links from a Release. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#get-links +func (s *ReleaseLinksService) ListReleaseLinks(pid interface{}, tagName string, opt *ListReleaseLinksOptions, options ...OptionFunc) ([]*ReleaseLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s/assets/links", url.QueryEscape(project), tagName) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var rls []*ReleaseLink + resp, err := s.client.Do(req, &rls) + if err != nil { + return nil, resp, err + } + + return rls, resp, err +} + +// GetReleaseLink returns a link from release assets. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#get-a-link +func (s *ReleaseLinksService) GetReleaseLink(pid interface{}, tagName string, link int, options ...OptionFunc) (*ReleaseLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s/assets/links/%d", + url.QueryEscape(project), + tagName, + link) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + rl := new(ReleaseLink) + resp, err := s.client.Do(req, rl) + if err != nil { + return nil, resp, err + } + + return rl, resp, err +} + +// CreateReleaseLinkOptions represents CreateReleaseLink() options. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#create-a-link +type CreateReleaseLinkOptions struct { + Name *string `url:"name" json:"name"` + URL *string `url:"url" json:"url"` +} + +// CreateReleaseLink creates a link. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#create-a-link +func (s *ReleaseLinksService) CreateReleaseLink(pid interface{}, tagName string, opt *CreateReleaseLinkOptions, options ...OptionFunc) (*ReleaseLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s/assets/links", url.QueryEscape(project), tagName) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + rl := new(ReleaseLink) + resp, err := s.client.Do(req, rl) + if err != nil { + return nil, resp, err + } + + return rl, resp, err +} + +// UpdateReleaseLinkOptions represents UpdateReleaseLink() options. +// +// You have to specify at least one of Name of URL. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#update-a-link +type UpdateReleaseLinkOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + URL *string `url:"url,omitempty" json:"url,omitempty"` +} + +// UpdateReleaseLink updates an asset link. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#update-a-link +func (s *ReleaseLinksService) UpdateReleaseLink(pid interface{}, tagName string, link int, opt *UpdateReleaseLinkOptions, options ...OptionFunc) (*ReleaseLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s/assets/links/%d", + url.QueryEscape(project), + tagName, + link) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + rl := new(ReleaseLink) + resp, err := s.client.Do(req, rl) + if err != nil { + return nil, resp, err + } + + return rl, resp, err +} + +// DeleteReleaseLink deletes a link from release. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#delete-a-link +func (s *ReleaseLinksService) DeleteReleaseLink(pid interface{}, tagName string, link int, options ...OptionFunc) (*ReleaseLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s/assets/links/%d", + url.QueryEscape(project), + tagName, + link, + ) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, nil, err + } + + rl := new(ReleaseLink) + resp, err := s.client.Do(req, rl) + if err != nil { + return nil, resp, err + } + + return rl, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/releases.go b/vendor/github.com/xanzy/go-gitlab/releases.go new file mode 100644 index 000000000..74c96ee28 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/releases.go @@ -0,0 +1,213 @@ +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// ReleasesService handles communication with the releases methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/releases/index.html +type ReleasesService struct { + client *Client +} + +// Release represents a project release. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#list-releases +type Release struct { + TagName string `json:"tag_name"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + DescriptionHTML string `json:"description_html,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + Author struct { + ID int `json:"id"` + Name string `json:"name"` + Username string `json:"username"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"author"` + Commit Commit `json:"commit"` + Assets struct { + Count int `json:"count"` + Sources []struct { + Format string `json:"format"` + URL string `json:"url"` + } `json:"sources"` + Links []*ReleaseLink `json:"links"` + } `json:"assets"` +} + +// ListReleasesOptions represents ListReleases() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#list-releases +type ListReleasesOptions ListOptions + +// ListReleases gets a pagenated of releases accessible by the authenticated user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#list-releases +func (s *ReleasesService) ListReleases(pid interface{}, opt *ListReleasesOptions, options ...OptionFunc) ([]*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var rs []*Release + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// GetRelease returns a single release, identified by a tag name. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#get-a-release-by-a-tag-name +func (s *ReleasesService) GetRelease(pid interface{}, tagName string, options ...OptionFunc) (*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s", url.QueryEscape(project), tagName) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + r := new(Release) + resp, err := s.client.Do(req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// ReleaseAssets represents release assets in CreateRelease() options +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release +type ReleaseAssets struct { + Links []*ReleaseAssetLink `url:"links" json:"links"` +} + +// ReleaseAssetLink represents release asset link in CreateRelease() options +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release +type ReleaseAssetLink struct { + Name string `url:"name" json:"name"` + URL string `url:"url" json:"url"` +} + +// CreateReleaseOptions represents CreateRelease() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release +type CreateReleaseOptions struct { + Name *string `url:"name" json:"name"` + TagName *string `url:"tag_name" json:"tag_name"` + Description *string `url:"description" json:"description"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Assets *ReleaseAssets `url:"assets,omitempty" json:"assets,omitempty"` +} + +// CreateRelease creates a release. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release +func (s *ReleasesService) CreateRelease(pid interface{}, opts *CreateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opts, options) + if err != nil { + return nil, nil, err + } + + r := new(Release) + resp, err := s.client.Do(req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// UpdateReleaseOptions represents UpdateRelease() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#update-a-release +type UpdateReleaseOptions struct { + Name *string `url:"name" json:"name"` + Description *string `url:"description" json:"description"` +} + +// UpdateRelease updates a release. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#update-a-release +func (s *ReleasesService) UpdateRelease(pid interface{}, tagName string, opts *UpdateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s", url.QueryEscape(project), tagName) + + req, err := s.client.NewRequest("PUT", u, opts, options) + if err != nil { + return nil, nil, err + } + + r := new(Release) + resp, err := s.client.Do(req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// DeleteRelease deletes a release. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/releases/index.html#delete-a-release +func (s *ReleasesService) DeleteRelease(pid interface{}, tagName string, options ...OptionFunc) (*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/releases/%s", url.QueryEscape(project), tagName) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, nil, err + } + + r := new(Release) + resp, err := s.client.Do(req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/runners.go b/vendor/github.com/xanzy/go-gitlab/runners.go index 960656c90..774906aad 100644 --- a/vendor/github.com/xanzy/go-gitlab/runners.go +++ b/vendor/github.com/xanzy/go-gitlab/runners.go @@ -18,7 +18,6 @@ package gitlab import ( "fmt" - "net" "net/url" "time" ) @@ -35,15 +34,15 @@ type RunnersService struct { // // GitLab API docs: https://docs.gitlab.com/ce/api/runners.html type Runner struct { - ID int `json:"id"` - Description string `json:"description"` - Active bool `json:"active"` - IsShared bool `json:"is_shared"` - IPAddress *net.IP `json:"ip_address"` - Name string `json:"name"` - Online bool `json:"online"` - Status string `json:"status"` - Token string `json:"token"` + ID int `json:"id"` + Description string `json:"description"` + Active bool `json:"active"` + IsShared bool `json:"is_shared"` + IPAddress string `json:"ip_address"` + Name string `json:"name"` + Online bool `json:"online"` + Status string `json:"status"` + Token string `json:"token"` } // RunnerDetails represents the GitLab CI runner details. diff --git a/vendor/github.com/xanzy/go-gitlab/tags.go b/vendor/github.com/xanzy/go-gitlab/tags.go index 4e8a7139d..d8b2023f4 100644 --- a/vendor/github.com/xanzy/go-gitlab/tags.go +++ b/vendor/github.com/xanzy/go-gitlab/tags.go @@ -33,16 +33,16 @@ type TagsService struct { // // GitLab API docs: https://docs.gitlab.com/ce/api/tags.html type Tag struct { - Commit *Commit `json:"commit"` - Release *Release `json:"release"` - Name string `json:"name"` - Message string `json:"message"` + Commit *Commit `json:"commit"` + Release *ReleaseNote `json:"release"` + Name string `json:"name"` + Message string `json:"message"` } -// Release represents a GitLab version release. +// ReleaseNote represents a GitLab version release. // // GitLab API docs: https://docs.gitlab.com/ce/api/tags.html -type Release struct { +type ReleaseNote struct { TagName string `json:"tag_name"` Description string `json:"description"` } @@ -118,9 +118,10 @@ func (s *TagsService) GetTag(pid interface{}, tag string, options ...OptionFunc) // GitLab API docs: // https://docs.gitlab.com/ce/api/tags.html#create-a-new-tag type CreateTagOptions struct { - TagName *string `url:"tag_name,omitempty" json:"tag_name,omitempty"` - Ref *string `url:"ref,omitempty" json:"ref,omitempty"` - Message *string `url:"message,omitempty" json:"message,omitempty"` + TagName *string `url:"tag_name,omitempty" json:"tag_name,omitempty"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Message *string `url:"message,omitempty" json:"message,omitempty"` + // ReleaseDescription parameter was deprecated in GitLab 11.7 ReleaseDescription *string `url:"release_description:omitempty" json:"release_description,omitempty"` } @@ -168,20 +169,24 @@ func (s *TagsService) DeleteTag(pid interface{}, tag string, options ...OptionFu return s.client.Do(req, nil) } -// CreateReleaseOptions represents the available CreateRelease() options. +// CreateReleaseNoteOptions represents the available CreateReleaseNote() options. +// +// Deprecated: This feature was deprecated in GitLab 11.7. // // GitLab API docs: // https://docs.gitlab.com/ce/api/tags.html#create-a-new-release -type CreateReleaseOptions struct { +type CreateReleaseNoteOptions struct { Description *string `url:"description:omitempty" json:"description,omitempty"` } -// CreateRelease Add release notes to the existing git tag. +// CreateReleaseNote Add release notes to the existing git tag. // If there already exists a release for the given tag, status code 409 is returned. // +// Deprecated: This feature was deprecated in GitLab 11.7. +// // GitLab API docs: // https://docs.gitlab.com/ce/api/tags.html#create-a-new-release -func (s *TagsService) CreateRelease(pid interface{}, tag string, opt *CreateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) { +func (s *TagsService) CreateReleaseNote(pid interface{}, tag string, opt *CreateReleaseNoteOptions, options ...OptionFunc) (*ReleaseNote, *Response, error) { project, err := parseID(pid) if err != nil { return nil, nil, err @@ -193,7 +198,7 @@ func (s *TagsService) CreateRelease(pid interface{}, tag string, opt *CreateRele return nil, nil, err } - r := new(Release) + r := new(ReleaseNote) resp, err := s.client.Do(req, r) if err != nil { return nil, resp, err @@ -202,19 +207,21 @@ func (s *TagsService) CreateRelease(pid interface{}, tag string, opt *CreateRele return r, resp, err } -// UpdateReleaseOptions represents the available UpdateRelease() options. +// UpdateReleaseNoteOptions represents the available UpdateReleaseNote() options. // // GitLab API docs: // https://docs.gitlab.com/ce/api/tags.html#update-a-release -type UpdateReleaseOptions struct { +type UpdateReleaseNoteOptions struct { Description *string `url:"description:omitempty" json:"description,omitempty"` } -// UpdateRelease Updates the release notes of a given release. +// UpdateReleaseNote Updates the release notes of a given release. +// +// Deprecated: This feature was deprecated in GitLab 11.7. // // GitLab API docs: // https://docs.gitlab.com/ce/api/tags.html#update-a-release -func (s *TagsService) UpdateRelease(pid interface{}, tag string, opt *UpdateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) { +func (s *TagsService) UpdateReleaseNote(pid interface{}, tag string, opt *UpdateReleaseNoteOptions, options ...OptionFunc) (*ReleaseNote, *Response, error) { project, err := parseID(pid) if err != nil { return nil, nil, err @@ -226,7 +233,7 @@ func (s *TagsService) UpdateRelease(pid interface{}, tag string, opt *UpdateRele return nil, nil, err } - r := new(Release) + r := new(ReleaseNote) resp, err := s.client.Do(req, r) if err != nil { return nil, resp, err diff --git a/vendor/github.com/xanzy/go-gitlab/todos.go b/vendor/github.com/xanzy/go-gitlab/todos.go index b563daa76..812181d40 100644 --- a/vendor/github.com/xanzy/go-gitlab/todos.go +++ b/vendor/github.com/xanzy/go-gitlab/todos.go @@ -67,7 +67,7 @@ type TodoTarget struct { Weight int `json:"weight"` // Only available for type MergeRequest - ApprovalsBeforeMerge bool `json:"approvals_before_merge"` + ApprovalsBeforeMerge int `json:"approvals_before_merge"` ForceRemoveSourceBranch bool `json:"force_remove_source_branch"` MergeCommitSHA string `json:"merge_commit_sha"` MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` diff --git a/vendor/github.com/xanzy/go-gitlab/users.go b/vendor/github.com/xanzy/go-gitlab/users.go index 6a2f7158f..b6e68b68b 100644 --- a/vendor/github.com/xanzy/go-gitlab/users.go +++ b/vendor/github.com/xanzy/go-gitlab/users.go @@ -22,6 +22,13 @@ import ( "time" ) +// List a couple of standard errors. +var ( + ErrUserBlockPrevented = errors.New("Cannot block a user that is already blocked by LDAP synchronization") + ErrUserNotFound = errors.New("User does not exist") + ErrUserUnblockPrevented = errors.New("Cannot unblock a user that is blocked by LDAP synchronization") +) + // UsersService handles communication with the user related methods of // the GitLab API. // @@ -425,7 +432,7 @@ func (s *UsersService) BlockUser(user int, options ...OptionFunc) error { } resp, err := s.client.Do(req, nil) - if err != nil { + if err != nil && resp == nil { return err } @@ -433,9 +440,9 @@ func (s *UsersService) BlockUser(user int, options ...OptionFunc) error { case 201: return nil case 403: - return errors.New("Cannot block a user that is already blocked by LDAP synchronization") + return ErrUserBlockPrevented case 404: - return errors.New("User does not exist") + return ErrUserNotFound default: return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode) } @@ -453,7 +460,7 @@ func (s *UsersService) UnblockUser(user int, options ...OptionFunc) error { } resp, err := s.client.Do(req, nil) - if err != nil { + if err != nil && resp == nil { return err } @@ -461,9 +468,9 @@ func (s *UsersService) UnblockUser(user int, options ...OptionFunc) error { case 201: return nil case 403: - return errors.New("Cannot unblock a user that is blocked by LDAP synchronization") + return ErrUserUnblockPrevented case 404: - return errors.New("User does not exist") + return ErrUserNotFound default: return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode) } diff --git a/vendor/modules.txt b/vendor/modules.txt index abd4d87a9..883155b67 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -162,7 +162,7 @@ github.com/ulikunitz/xz github.com/ulikunitz/xz/internal/xlog github.com/ulikunitz/xz/lzma github.com/ulikunitz/xz/internal/hash -# github.com/xanzy/go-gitlab v0.14.1 +# github.com/xanzy/go-gitlab v0.16.1 github.com/xanzy/go-gitlab # github.com/zclconf/go-cty v0.0.0-20180302160414-49fa5e03c418 github.com/zclconf/go-cty/cty From 9a67927594abd9e74b4ec8e0a6f49f1fc432356c Mon Sep 17 00:00:00 2001 From: Usama Ahmad Date: Wed, 24 Apr 2019 10:25:27 +0500 Subject: [PATCH 23/29] Updated access levels --- gitlab/resource_gitlab_branch_protection.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gitlab/resource_gitlab_branch_protection.go b/gitlab/resource_gitlab_branch_protection.go index c2654ff8e..271f44fdb 100644 --- a/gitlab/resource_gitlab_branch_protection.go +++ b/gitlab/resource_gitlab_branch_protection.go @@ -8,9 +8,10 @@ import ( ) func resourceGitlabBranchProtection() *schema.Resource { - acceptedAccessLevels := []string{ - "master", - "developer", + acceptedAccessLevels := make([]string, 0, len(accessLevelID)) + + for k := range accessLevelID { + acceptedAccessLevels = append(acceptedAccessLevels, k) } return &schema.Resource{ Create: resourceGitlabBranchProtectionCreate, From 51b4200a9fc7ce1ae1a242ff8ce9eb3c92aa4fcd Mon Sep 17 00:00:00 2001 From: Usama Ahmad Date: Wed, 24 Apr 2019 10:25:50 +0500 Subject: [PATCH 24/29] Added test cases for protected branch --- .../resource_gitlab_branch_protection_test.go | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 gitlab/resource_gitlab_branch_protection_test.go diff --git a/gitlab/resource_gitlab_branch_protection_test.go b/gitlab/resource_gitlab_branch_protection_test.go new file mode 100644 index 000000000..5d96edbee --- /dev/null +++ b/gitlab/resource_gitlab_branch_protection_test.go @@ -0,0 +1,176 @@ +package gitlab + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/xanzy/go-gitlab" +) + +func TestAccGitlabBranchProtection_basic(t *testing.T) { + + var pb gitlab.ProtectedBranch + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGitlabBranchProtectionDestroy, + Steps: []resource.TestStep{ + // Create a project and Branch Protection with default options + { + Config: testAccGitlabBranchProtectionConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.BranchProtect", &pb), + testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{ + Name: fmt.Sprintf("BranchProtect-%d", rInt), + PushAccessLevel: accessLevel[gitlab.DeveloperPermissions], + MergeAccessLevel: accessLevel[gitlab.DeveloperPermissions], + }), + ), + }, + // Update the Branch Protection + { + Config: testAccGitlabBranchProtectionUpdateConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.BranchProtect", &pb), + testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{ + Name: fmt.Sprintf("BranchProtect-%d", rInt), + PushAccessLevel: accessLevel[gitlab.MasterPermissions], + MergeAccessLevel: accessLevel[gitlab.MasterPermissions], + }), + ), + }, + // Update the Branch Protection to get back to initial settings + { + Config: testAccGitlabBranchProtectionConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.BranchProtect", &pb), + testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{ + Name: fmt.Sprintf("BranchProtect-%d", rInt), + PushAccessLevel: accessLevel[gitlab.DeveloperPermissions], + MergeAccessLevel: accessLevel[gitlab.DeveloperPermissions], + }), + ), + }, + }, + }) +} + +func testAccCheckGitlabBranchProtectionExists(n string, pb *gitlab.ProtectedBranch) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not Found: %s", n) + } + project, branch, err := projectAndBranchFromID(rs.Primary.ID) + if err != nil { + return fmt.Errorf("Error in Splitting Project and Branch Ids") + } + + conn := testAccProvider.Meta().(*gitlab.Client) + + pbs, _, err := conn.ProtectedBranches.ListProtectedBranches(project, nil) + if err != nil { + return err + } + for _, gotpb := range pbs { + if gotpb.Name == branch { + *pb = *gotpb + return nil + } + } + return fmt.Errorf("Protected Branch does not exist") + } +} + +type testAccGitlabBranchProtectionExpectedAttributes struct { + Name string + PushAccessLevel string + MergeAccessLevel string +} + +func testAccCheckGitlabBranchProtectionAttributes(pb *gitlab.ProtectedBranch, want *testAccGitlabBranchProtectionExpectedAttributes) resource.TestCheckFunc { + return func(s *terraform.State) error { + if pb.Name != want.Name { + return fmt.Errorf("got name %q; want %q", pb.Name, want.Name) + } + + if pb.PushAccessLevels[0].AccessLevel != accessLevelID[want.PushAccessLevel] { + return fmt.Errorf("got Push access levels %q; want %q", pb.PushAccessLevels[0].AccessLevel, accessLevelID[want.PushAccessLevel]) + } + + if pb.MergeAccessLevels[0].AccessLevel != accessLevelID[want.MergeAccessLevel] { + return fmt.Errorf("got Merge access levels %q; want %q", pb.MergeAccessLevels[0].AccessLevel, accessLevelID[want.MergeAccessLevel]) + } + + return nil + } +} + +func testAccCheckGitlabBranchProtectionDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*gitlab.Client) + var project string + var branch string + for _, rs := range s.RootModule().Resources { + if rs.Type == "gitlab_project" { + project = rs.Primary.ID + } else if rs.Type == "gitlab_branch_protection" { + branch = rs.Primary.ID + } + } + + pb, response, err := conn.ProtectedBranches.GetProtectedBranch(project, branch) + if err == nil { + if pb != nil { + return fmt.Errorf("project branch protection %s still exists", branch) + } + } + if response.StatusCode != 404 { + return err + } + return nil +} + +func testAccGitlabBranchProtectionConfig(rInt int) string { + return fmt.Sprintf(` +resource "gitlab_project" "foo" { + name = "foo-%d" + description = "Terraform acceptance tests" + + # So that acceptance tests can be run in a gitlab organization + # with no billing + visibility_level = "public" +} + +resource "gitlab_branch_protection" "BranchProtect" { + project = "${gitlab_project.foo.id}" + branch = "BranchProtect-%d" + push_access_level = "developer" + merge_access_level = "developer" +} + `, rInt, rInt) +} + +func testAccGitlabBranchProtectionUpdateConfig(rInt int) string { + return fmt.Sprintf(` +resource "gitlab_project" "foo" { + name = "foo-%d" + description = "Terraform acceptance tests" + + # So that acceptance tests can be run in a gitlab organization + # with no billing + visibility_level = "public" +} + +resource "gitlab_branch_protection" "BranchProtect" { + project = "${gitlab_project.foo.id}" + branch = "BranchProtect-%d" + push_access_level = "maintainer" + merge_access_level = "maintainer" +} + `, rInt, rInt) +} From 2978c43b869396e2ce9d5e7587dec4d9c502ecdf Mon Sep 17 00:00:00 2001 From: Usama Ahmad Date: Wed, 24 Apr 2019 11:41:29 +0500 Subject: [PATCH 25/29] Documentation for branch protection --- .../docs/r/branch_protection.html.markdown | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 website/docs/r/branch_protection.html.markdown diff --git a/website/docs/r/branch_protection.html.markdown b/website/docs/r/branch_protection.html.markdown new file mode 100644 index 000000000..2495980cb --- /dev/null +++ b/website/docs/r/branch_protection.html.markdown @@ -0,0 +1,34 @@ +--- +layout: "gitlab" +page_title: "GitLab: gitlab_branch_protection" +sidebar_current: "docs-gitlab-resource-branch_protection" +description: |- + Protects a branch by assigning access levels to it +--- + +# gitlab\_branch_protection + +This resource allows you to protect a specific branch by an access level so that the user with less access level cannot Merge/Push to the branch. + +## Example Usage + +```hcl +resource "gitlab_branch_protection" "BranchProtect" { + project = "12345" + branch = "BranchProtected" + push_access_level = "developer" + merge_access_level = "developer" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - (Required) The id of the project. + +* `branch` - (Required) Name of the branch. + +* `push_access_level` - (Required) One of five levels of access to the project. + +* `merge_access_level` - (Required) One of five levels of access to the project. \ No newline at end of file From 8ff8d45ea6339b51cdafc12afbba2128faf647be Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 1 May 2019 14:30:14 +0200 Subject: [PATCH 26/29] Fix acc tests Signed-off-by: Julien Pivotto --- .travis.yml | 45 ++++++++++++++++++++------------ scripts/generate-access-token.rb | 3 +++ scripts/start-gitlab.sh | 3 ++- 3 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 scripts/generate-access-token.rb diff --git a/.travis.yml b/.travis.yml index 452b1ad8c..cfa8e6430 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,32 @@ -dist: trusty -sudo: required -services: -- docker language: go -go: - - "1.11.x" -env: - - GOFLAGS=-mod=vendor GO111MODULE=on GITLAB_BASE_URL=http://127.0.0.1:8080/api/v4 GITLAB_TOKEN=ACCTEST +matrix: + fast_finish: false + include: + - name: unit tests + env: MAKE_TARGET=test GOFLAGS=-mod=vendor GO111MODULE=on + go: "1.11.x" + - name: acceptance tests + env: MAKE_TARGET=testacc GOFLAGS=-mod=vendor GO111MODULE=on GITLAB_BASE_URL=http://127.0.0.1:8080/api/v4 GITLAB_TOKEN=ACCTEST + go: "1.11.x" + - name: govet tests + env: MAKE_TARGET=vet GOFLAGS=-mod=vendor GO111MODULE=on + go: "1.11.x" + - name: website tests + env: MAKE_TARGET=website-test GOFLAGS=-mod=vendor GO111MODULE=on + go: "1.11.x" + - name: unit tests (go 1.12) + env: MAKE_TARGET=test GOFLAGS=-mod=vendor GO111MODULE=on + go: "1.12.x" + - name: unit tests (go tip) + env: MAKE_TARGET=test GOFLAGS=-mod=vendor GO111MODULE=on + go: tip + allow_failures: + - name: unit tests (go tip) + env: MAKE_TARGET=test GOFLAGS=-mod=vendor GO111MODULE=on + go: tip + - name: unit tests (go 1.12) + env: MAKE_TARGET=test GOFLAGS=-mod=vendor GO111MODULE=on + go: "1.12.x" install: # This script is used by the Travis build to install a cookie for @@ -17,15 +37,8 @@ install: - bash scripts/start-gitlab.sh script: -- make test -- make testacc -- make vet -- make website-test +- make $MAKE_TARGET branches: only: - master -matrix: - fast_finish: true - allow_failures: - - go: tip diff --git a/scripts/generate-access-token.rb b/scripts/generate-access-token.rb new file mode 100644 index 000000000..8bbbc29ef --- /dev/null +++ b/scripts/generate-access-token.rb @@ -0,0 +1,3 @@ +terraform_token = PersonalAccessToken.create(user_id: 1, scopes: [:api, :read_user], name: :terraform) +terraform_token.set_token(:ACCTEST) +terraform_token.save! diff --git a/scripts/start-gitlab.sh b/scripts/start-gitlab.sh index 7f781551e..1ac839442 100755 --- a/scripts/start-gitlab.sh +++ b/scripts/start-gitlab.sh @@ -1,4 +1,5 @@ #!/bin/bash -e +if [[ $MAKE_TARGET != "testacc" ]]; then echo "not starting gitlab!"; exit 0; fi echo "Starting gitlab container..." docker run -d -e GITLAB_ROOT_PASSWORD=adminadmin --rm -p 127.0.0.1:8080:80 --name gitlab gitlab/gitlab-ce echo -n "Waiting for gitlab to be ready " @@ -12,4 +13,4 @@ do done echo echo "Creating access token" -echo 'PersonalAccessToken.create(user_id: 1, scopes: [:api, :read_user], name: :terraform, token: :ACCTEST).save!' | docker exec -i gitlab gitlab-rails console +docker exec -i gitlab gitlab-rails console < scripts/generate-access-token.rb From 287bf3fd94d96b972509054d740eed557027c4e8 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 1 May 2019 16:09:54 +0200 Subject: [PATCH 27/29] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b21335eaf..fee71f606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,15 @@ ## 1.2.1 (Unreleased) +FEATURES: +* **New Resource:** `gitlab_service_slack` ([#96](https://github.com/terraform-providers/terraform-provider-gitlab/issues/96)) + ENHANCEMENTS: * Support for request/response logging when >`DEBUG` severity is set ([#93](https://github.com/terraform-providers/terraform-provider-gitlab/issues/93)) +* Datasource `gitlab_user` supports user_id, email lookup and return lots of new attributes ([#102](https://github.com/terraform-providers/terraform-provider-gitlab/issues/102)) +* Resource `gitlab_deploy_key` can now be imported ([#197](https://github.com/terraform-providers/terraform-provider-gitlab/issues/97)) + +BUGFIXES: +* Documentation fixes ([#108](https://github.com/terraform-providers/terraform-provider-gitlab/issues/108), [#113](https://github.com/terraform-providers/terraform-provider-gitlab/issues/113)) ## 1.2.0 (February 19, 2019) From 6c62c669a869affab38f804c044b6a263f6e664a Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 1 May 2019 16:10:15 +0200 Subject: [PATCH 28/29] Bump next version to 1.3.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fee71f606..2cdaa1e52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.2.1 (Unreleased) +## 1.3.0 (Unreleased) FEATURES: * **New Resource:** `gitlab_service_slack` ([#96](https://github.com/terraform-providers/terraform-provider-gitlab/issues/96)) From 3ddf4aeb3c7e14cbe95bd3987ebdcff98f9e5af2 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Thu, 2 May 2019 13:37:22 +0200 Subject: [PATCH 29/29] Fix test about slack Signed-off-by: Julien Pivotto --- gitlab/resource_gitlab_service_slack_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab/resource_gitlab_service_slack_test.go b/gitlab/resource_gitlab_service_slack_test.go index 2bb3ff0ef..d5a3348d3 100644 --- a/gitlab/resource_gitlab_service_slack_test.go +++ b/gitlab/resource_gitlab_service_slack_test.go @@ -131,7 +131,7 @@ func testAccCheckGitlabServiceSlackDestroy(s *terraform.State) error { continue } - gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID) + gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil) if err == nil { if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID { return fmt.Errorf("Repository still exists")