Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add new google_cloudbuild_trigger resource #1357

Merged
merged 9 commits into from
May 7, 2018
9 changes: 9 additions & 0 deletions google/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"golang.org/x/oauth2/jwt"
"google.golang.org/api/bigquery/v2"
"google.golang.org/api/cloudbilling/v1"
"google.golang.org/api/cloudbuild/v1"
"google.golang.org/api/cloudfunctions/v1"
"google.golang.org/api/cloudiot/v1"
"google.golang.org/api/cloudkms/v1"
Expand Down Expand Up @@ -54,6 +55,7 @@ type Config struct {
tokenSource oauth2.TokenSource

clientBilling *cloudbilling.Service
clientBuild *cloudbuild.Service
clientCompute *compute.Service
clientComputeBeta *computeBeta.Service
clientContainer *container.Service
Expand Down Expand Up @@ -268,6 +270,13 @@ func (c *Config) loadAndValidate() error {
}
c.clientBilling.UserAgent = userAgent

log.Printf("[INFO] Instantiating Google Cloud Build Client...")
c.clientBuild, err = cloudbuild.New(client)
if err != nil {
return err
}
c.clientBuild.UserAgent = userAgent

log.Printf("[INFO] Instantiating Google Cloud BigQuery Client...")
c.clientBigQuery, err = bigquery.New(client)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func Provider() terraform.ResourceProvider {
"google_bigquery_table": resourceBigQueryTable(),
"google_bigtable_instance": resourceBigtableInstance(),
"google_bigtable_table": resourceBigtableTable(),
"google_cloudbuild_trigger": resourceCloudBuildTrigger(),
"google_cloudfunctions_function": resourceCloudFunctionsFunction(),
"google_cloudiot_registry": resourceCloudIoTRegistry(),
"google_compute_autoscaler": resourceComputeAutoscaler(),
Expand Down
300 changes: 300 additions & 0 deletions google/resource_cloudbuild_build_trigger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
// Package google - implement CRUD operations for Container Registry Build Triggers
// https://cloud.google.com/container-builder/docs/api/reference/rest/v1/projects.triggers#BuildTrigger
package google

import (
"encoding/json"
"fmt"
"log"
"strings"
"time"

"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudbuild/v1"
)

func resourceCloudBuildTrigger() *schema.Resource {
return &schema.Resource{
Create: resourceCloudbuildBuildTriggerCreate,
Read: resourceCloudbuildBuildTriggerRead,
Delete: resourceCloudbuildBuildTriggerDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(5 * time.Minute),
Delete: schema.DefaultTimeout(3 * time.Minute),
},

SchemaVersion: 1,

Schema: map[string]*schema.Schema{
"project": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"build": {
Type: schema.TypeList,
Description: "Contents of the build template.",
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"images": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"step": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"args": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
},
},
},
"tags": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"trigger_template": &schema.Schema{
Optional: true,
Type: schema.TypeList,
MaxItems: 1,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"branch_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"commit_sha": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"dir": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"project": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"repo_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"tag_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
},
},
},
},
}
}

func resourceCloudbuildBuildTriggerCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

project, err := getProject(d, config)
if err != nil {
return err
}

// Build the address parameter
buildTrigger := &cloudbuild.BuildTrigger{}

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

buildTrigger.Build = expandCloudbuildBuildTriggerBuild(d)
buildTrigger.TriggerTemplate = expandCloudbuildBuildTriggerTemplate(d, project)

tstr, err := json.Marshal(buildTrigger)
if err != nil {
return err
}
log.Printf("[INFO] build trigger request: %s", string(tstr))
trigger, err := config.clientBuild.Projects.Triggers.Create(project, buildTrigger).Do()
if err != nil {
return fmt.Errorf("Error creating build trigger: %s", err)
}

d.SetId(trigger.Id)

return resourceCloudbuildBuildTriggerRead(d, meta)
}

func resourceCloudbuildBuildTriggerRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

project, err := getProject(d, config)
if err != nil {
return err
}

ID := d.Id()
buildTrigger, err := config.clientBuild.Projects.Triggers.Get(project, ID).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Cloudbuild Trigger %q", ID))
}

d.Set("description", buildTrigger.Description)

if buildTrigger.TriggerTemplate != nil {
d.Set("trigger_template", flattenCloudbuildBuildTriggerTemplate(d, config, buildTrigger.TriggerTemplate))
}
if buildTrigger.Build != nil {
d.Set("build", flattenCloudbuildBuildTriggerBuild(d, config, buildTrigger.Build))
}

return nil
}

func expandCloudbuildBuildTriggerTemplate(d *schema.ResourceData, project string) *cloudbuild.RepoSource {
if d.Get("trigger_template.#").(int) == 0 {
return nil
}
tmpl := &cloudbuild.RepoSource{}
if v, ok := d.GetOk("project"); ok {
tmpl.ProjectId = v.(string)
} else {
tmpl.ProjectId = project
}
if v, ok := d.GetOk("trigger_template.0.branch_name"); ok {
tmpl.BranchName = v.(string)
}
if v, ok := d.GetOk("trigger_template.0.commit_sha"); ok {
tmpl.CommitSha = v.(string)
}
if v, ok := d.GetOk("trigger_template.0.dir"); ok {
tmpl.Dir = v.(string)
}
if v, ok := d.GetOk("trigger_template.0.repo_name"); ok {
tmpl.RepoName = v.(string)
}
if v, ok := d.GetOk("trigger_template.0.tag_name"); ok {
tmpl.TagName = v.(string)
}
return tmpl
}

func flattenCloudbuildBuildTriggerTemplate(d *schema.ResourceData, config *Config, t *cloudbuild.RepoSource) []map[string]interface{} {
flattened := make([]map[string]interface{}, 1)

flattened[0] = map[string]interface{}{
"branch_name": t.BranchName,
"commit_sha": t.CommitSha,
"dir": t.Dir,
"project": t.ProjectId,
"repo_name": t.RepoName,
"tag_name": t.TagName,
}

return flattened
}

func expandCloudbuildBuildTriggerBuild(d *schema.ResourceData) *cloudbuild.Build {
if d.Get("build.#").(int) == 0 {
return nil
}

build := &cloudbuild.Build{}
if v, ok := d.GetOk("build.0.images"); ok {
build.Images = convertStringArr(v.([]interface{}))
}
if v, ok := d.GetOk("build.0.tags"); ok {
build.Tags = convertStringArr(v.([]interface{}))
}
stepCount := d.Get("build.0.step.#").(int)
build.Steps = make([]*cloudbuild.BuildStep, 0, stepCount)
for s := 0; s < stepCount; s++ {
step := &cloudbuild.BuildStep{
Name: d.Get(fmt.Sprintf("build.0.step.%d.name", s)).(string),
}
if v, ok := d.GetOk(fmt.Sprintf("build.0.step.%d.args", s)); ok {
step.Args = strings.Split(v.(string), " ")
}
build.Steps = append(build.Steps, step)
}
return build
}

func flattenCloudbuildBuildTriggerBuild(d *schema.ResourceData, config *Config, b *cloudbuild.Build) []map[string]interface{} {
flattened := make([]map[string]interface{}, 1)

flattened[0] = map[string]interface{}{}

if b.Images != nil {
flattened[0]["images"] = convertStringArrToInterface(b.Images)
}
if b.Tags != nil {
flattened[0]["tags"] = convertStringArrToInterface(b.Tags)
}
if b.Steps != nil {
steps := make([]map[string]interface{}, len(b.Steps))
for i, step := range b.Steps {
steps[i] = map[string]interface{}{}
steps[i]["name"] = step.Name
steps[i]["args"] = strings.Join(step.Args, " ")
}
flattened[0]["step"] = steps
}

return flattened
}

func resourceCloudbuildBuildTriggerDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

project, err := getProject(d, config)
if err != nil {
return err
}

// Delete the build trigger
log.Printf("[DEBUG] build trigger delete request")
_, err = config.clientBuild.Projects.Triggers.Delete(
project, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error deleting build trigger: %s", err)
}

d.SetId("")
return nil
}
Loading