diff --git a/gitlab/provider.go b/gitlab/provider.go index cf6bb07df..de1e309d5 100644 --- a/gitlab/provider.go +++ b/gitlab/provider.go @@ -51,6 +51,7 @@ func Provider() terraform.ResourceProvider { "gitlab_group": resourceGitlabGroup(), "gitlab_project": resourceGitlabProject(), "gitlab_label": resourceGitlabLabel(), + "gitlab_pipeline_trigger": resourceGitlabPipelineTrigger(), "gitlab_project_hook": resourceGitlabProjectHook(), "gitlab_deploy_key": resourceGitlabDeployKey(), "gitlab_user": resourceGitlabUser(), diff --git a/gitlab/resource_gitlab_pipeline_trigger.go b/gitlab/resource_gitlab_pipeline_trigger.go new file mode 100644 index 000000000..dbcc4b90e --- /dev/null +++ b/gitlab/resource_gitlab_pipeline_trigger.go @@ -0,0 +1,133 @@ +package gitlab + +import ( + "fmt" + "log" + "strconv" + + "github.com/hashicorp/terraform/helper/schema" + gitlab "github.com/xanzy/go-gitlab" +) + +func resourceGitlabPipelineTrigger() *schema.Resource { + return &schema.Resource{ + Create: resourceGitlabPipelineTriggerCreate, + Read: resourceGitlabPipelineTriggerRead, + Update: resourceGitlabPipelineTriggerUpdate, + Delete: resourceGitlabPipelineTriggerDelete, + + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Required: true, + }, + "token": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceGitlabPipelineTriggerCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + options := &gitlab.AddPipelineTriggerOptions{ + Description: gitlab.String(d.Get("description").(string)), + } + + log.Printf("[DEBUG] create gitlab PipelineTrigger %s", *options.Description) + + PipelineTrigger, _, err := client.PipelineTriggers.AddPipelineTrigger(project, options) + if err != nil { + return err + } + + d.SetId(strconv.Itoa(PipelineTrigger.ID)) + + return resourceGitlabPipelineTriggerRead(d, meta) +} + +func resourceGitlabPipelineTriggerRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + pipelineTriggerID, err := strconv.Atoi(d.Id()) + + if err != nil { + return fmt.Errorf("%s cannot be converted to int", d.Id()) + } + + log.Printf("[DEBUG] read gitlab PipelineTrigger %s/%d", project, pipelineTriggerID) + + pipelineTriggers, response, err := client.PipelineTriggers.ListPipelineTriggers(project, nil) + if err != nil { + if response.StatusCode == 404 { + log.Printf("[WARN] removing PipelineTrigger %d from state because it no longer exists in gitlab", pipelineTriggerID) + d.SetId("") + return nil + } + + return err + } + found := false + for _, pipelineTrigger := range pipelineTriggers { + if pipelineTrigger.ID == pipelineTriggerID { + d.Set("description", pipelineTrigger.Description) + d.Set("token", pipelineTrigger.Token) + found = true + break + } + } + if !found { + log.Printf("[WARN] removing PipelineTrigger %d from state because it no longer exists in gitlab", pipelineTriggerID) + d.SetId("") + } + + return nil +} + +func resourceGitlabPipelineTriggerUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + options := &gitlab.EditPipelineTriggerOptions{ + Description: gitlab.String(d.Get("description").(string)), + } + + pipelineTriggerID, err := strconv.Atoi(d.Id()) + + if err != nil { + return fmt.Errorf("%s cannot be converted to int", d.Id()) + } + + if d.HasChange("description") { + options.Description = gitlab.String(d.Get("description").(string)) + } + + log.Printf("[DEBUG] update gitlab PipelineTrigger %s", d.Id()) + + _, _, err = client.PipelineTriggers.EditPipelineTrigger(project, pipelineTriggerID, options) + if err != nil { + return err + } + + return resourceGitlabPipelineTriggerRead(d, meta) +} + +func resourceGitlabPipelineTriggerDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gitlab.Client) + project := d.Get("project").(string) + log.Printf("[DEBUG] Delete gitlab PipelineTrigger %s", d.Id()) + + pipelineTriggerID, err := strconv.Atoi(d.Id()) + + if err != nil { + return fmt.Errorf("%s cannot be converted to int", d.Id()) + } + + _, err = client.PipelineTriggers.DeletePipelineTrigger(project, pipelineTriggerID) + return err +} diff --git a/gitlab/resource_gitlab_pipeline_trigger_test.go b/gitlab/resource_gitlab_pipeline_trigger_test.go new file mode 100644 index 000000000..0ef41aff2 --- /dev/null +++ b/gitlab/resource_gitlab_pipeline_trigger_test.go @@ -0,0 +1,155 @@ +package gitlab + +import ( + "fmt" + "strconv" + "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 TestAccGitlabPipelineTrigger_basic(t *testing.T) { + var trigger gitlab.PipelineTrigger + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGitlabPipelineTriggerDestroy, + Steps: []resource.TestStep{ + // Create a project and pipeline trigger with default options + { + Config: testAccGitlabPipelineTriggerConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabPipelineTriggerExists("gitlab_pipeline_trigger.trigger", &trigger), + testAccCheckGitlabPipelineTriggerAttributes(&trigger, &testAccGitlabPipelineTriggerExpectedAttributes{ + Description: "External Pipeline Trigger", + }), + ), + }, + // Update the pipeline trigger to change the parameters + { + Config: testAccGitlabPipelineTriggerUpdateConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabPipelineTriggerExists("gitlab_pipeline_trigger.trigger", &trigger), + testAccCheckGitlabPipelineTriggerAttributes(&trigger, &testAccGitlabPipelineTriggerExpectedAttributes{ + Description: "Trigger", + }), + ), + }, + // Update the pipeline trigger to get back to initial settings + { + Config: testAccGitlabPipelineTriggerConfig(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckGitlabPipelineTriggerExists("gitlab_pipeline_trigger.trigger", &trigger), + testAccCheckGitlabPipelineTriggerAttributes(&trigger, &testAccGitlabPipelineTriggerExpectedAttributes{ + Description: "External Pipeline Trigger", + }), + ), + }, + }, + }) +} + +func testAccCheckGitlabPipelineTriggerExists(n string, trigger *gitlab.PipelineTrigger) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not Found: %s", n) + } + + triggerID := rs.Primary.ID + repoName := rs.Primary.Attributes["project"] + if repoName == "" { + return fmt.Errorf("No project ID is set") + } + conn := testAccProvider.Meta().(*gitlab.Client) + + triggers, _, err := conn.PipelineTriggers.ListPipelineTriggers(repoName, nil) + if err != nil { + return err + } + for _, gotTrigger := range triggers { + if strconv.Itoa(gotTrigger.ID) == triggerID { + *trigger = *gotTrigger + return nil + } + } + return fmt.Errorf("Pipeline Trigger does not exist") + } +} + +type testAccGitlabPipelineTriggerExpectedAttributes struct { + Description string +} + +func testAccCheckGitlabPipelineTriggerAttributes(trigger *gitlab.PipelineTrigger, want *testAccGitlabPipelineTriggerExpectedAttributes) resource.TestCheckFunc { + return func(s *terraform.State) error { + if trigger.Description != want.Description { + return fmt.Errorf("got description %q; want %q", trigger.Description, want.Description) + } + + return nil + } +} + +func testAccCheckGitlabPipelineTriggerDestroy(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 testAccGitlabPipelineTriggerConfig(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_pipeline_trigger" "trigger" { + project = "${gitlab_project.foo.id}" + description = "External Pipeline Trigger" +} + `, rInt) +} + +func testAccGitlabPipelineTriggerUpdateConfig(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_pipeline_trigger" "trigger" { + project = "${gitlab_project.foo.id}" + description = "Trigger" +} + `, rInt) +} diff --git a/website/docs/r/pipeline_trigger.html.markdown b/website/docs/r/pipeline_trigger.html.markdown new file mode 100644 index 000000000..5ec6fd9af --- /dev/null +++ b/website/docs/r/pipeline_trigger.html.markdown @@ -0,0 +1,28 @@ +--- +layout: "gitlab" +page_title: "GitLab: gitlab_pipeline_trigger" +sidebar_current: "docs-gitlab-resource-pipeline-trigger" +description: |- + Creates and manages pipeline triggers for GitLab projects +--- + +# gitlab\_pipeline\_trigger + +This resource allows you to create and manage pipeline triggers + +## Example Usage + +```hcl +resource "gitlab_pipeline_trigger" "example" { + project = "12345" + description = "Used to trigger builds" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - (Required, string) The name or id of the project to add the trigger to. + +* `description` - (Required, string) The description of the pipeline trigger. diff --git a/website/gitlab.erb b/website/gitlab.erb index 5a985d8d8..7f3423dee 100644 --- a/website/gitlab.erb +++ b/website/gitlab.erb @@ -43,6 +43,9 @@ > gitlab_label + > + gitlab_pipeline_trigger + > gitlab_project