Autogenerate google_cloudbuild_trigger (#2790)

This commit is contained in:
The Magician 2019-01-04 13:47:52 -08:00 committed by Riley Karson
parent 48a2cf8a27
commit 4ecc56a301
8 changed files with 1048 additions and 737 deletions

View File

@ -117,6 +117,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
return mergeResourceMaps(
GeneratedAppengineResourcesMap,
GeneratedComputeResourcesMap,
GeneratedCloudbuildResourcesMap,
GeneratedDnsResourcesMap,
GeneratedRedisResourcesMap,
GeneratedResourceManagerResourcesMap,
@ -132,7 +133,6 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
"google_billing_account_iam_binding": ResourceIamBindingWithImport(IamBillingAccountSchema, NewBillingAccountIamUpdater, BillingAccountIdParseFunc),
"google_billing_account_iam_member": ResourceIamMemberWithImport(IamBillingAccountSchema, NewBillingAccountIamUpdater, BillingAccountIdParseFunc),
"google_billing_account_iam_policy": ResourceIamPolicyWithImport(IamBillingAccountSchema, NewBillingAccountIamUpdater, BillingAccountIdParseFunc),
"google_cloudbuild_trigger": resourceCloudBuildTrigger(),
"google_cloudfunctions_function": resourceCloudFunctionsFunction(),
"google_cloudiot_registry": resourceCloudIoTRegistry(),
"google_composer_environment": resourceComposerEnvironment(),

View File

@ -0,0 +1,21 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import "github.com/hashicorp/terraform/helper/schema"
var GeneratedCloudbuildResourcesMap = map[string]*schema.Resource{
"google_cloudbuild_trigger": resourceCloudbuildTrigger(),
}

View File

@ -1,386 +0,0 @@
// 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,
Update: resourceCloudbuildBuildTriggerUpdate,
Delete: resourceCloudbuildBuildTriggerDelete,
Importer: &schema.ResourceImporter{
State: resourceCloudBuildTriggerImportState,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(5 * time.Minute),
Delete: schema.DefaultTimeout(3 * time.Minute),
},
SchemaVersion: 1,
Schema: map[string]*schema.Schema{
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"filename": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"build"},
},
"build": {
Type: schema.TypeList,
Description: "Contents of the build template.",
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"images": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"step": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
},
"args": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"tags": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"substitutions": {
Optional: true,
Type: schema.TypeMap,
Elem: &schema.Schema{Type: schema.TypeString},
},
"included_files": {
Optional: true,
Type: schema.TypeList,
MaxItems: 50,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"ignored_files": {
Optional: true,
Type: schema.TypeList,
MaxItems: 50,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"trigger_template": {
Optional: true,
Type: schema.TypeList,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"branch_name": {
Type: schema.TypeString,
Optional: true,
},
"commit_sha": {
Type: schema.TypeString,
Optional: true,
},
"dir": {
Type: schema.TypeString,
Optional: true,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"repo_name": {
Type: schema.TypeString,
Optional: true,
},
"tag_name": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"trigger_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceCloudbuildBuildTriggerCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
}
buildTrigger, err := expandCloudbuildBuildTrigger(d, meta)
if err != nil {
return err
}
buildTrigger.IgnoredFiles = expandStringSlice(d, "ignored_files")
buildTrigger.IncludedFiles = expandStringSlice(d, "included_files")
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)
d.Set("substitutions", buildTrigger.Substitutions)
d.Set("ignored_files", buildTrigger.IgnoredFiles)
d.Set("included_files", buildTrigger.IncludedFiles)
d.Set("trigger_id", buildTrigger.Id)
if buildTrigger.TriggerTemplate != nil {
d.Set("trigger_template", flattenCloudbuildBuildTriggerTemplate(d, config, buildTrigger.TriggerTemplate))
}
if buildTrigger.Filename != "" {
d.Set("filename", buildTrigger.Filename)
} else if buildTrigger.Build != nil {
d.Set("build", flattenCloudbuildBuildTriggerBuild(d, config, buildTrigger.Build))
}
return nil
}
func resourceCloudbuildBuildTriggerUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
}
buildTrigger, err := expandCloudbuildBuildTrigger(d, meta)
if err != nil {
return err
}
buildTrigger.Id = d.Get("trigger_id").(string)
id := d.Id()
log.Printf("[INFO] Updating Cloud Build Trigger: %s", id)
if _, err = config.clientBuild.Projects.Triggers.Patch(project, id, buildTrigger).Do(); err != nil {
return err
}
return resourceCloudbuildBuildTriggerRead(d, meta)
}
func expandCloudbuildBuildTrigger(d *schema.ResourceData, meta interface{}) (*cloudbuild.BuildTrigger, error) {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return nil, err
}
t := &cloudbuild.BuildTrigger{}
if v, ok := d.GetOk("description"); ok {
t.Description = v.(string)
}
if v, ok := d.GetOk("filename"); ok {
t.Filename = v.(string)
} else {
t.Build = expandCloudbuildBuildTriggerBuild(d)
}
t.Substitutions = expandStringMap(d, "substitutions")
t.TriggerTemplate = expandCloudbuildBuildTriggerTemplate(d, project)
return t, 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("trigger_template.0.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
}
func resourceCloudBuildTriggerImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) == 1 {
return []*schema.ResourceData{d}, nil
} else if len(parts) == 2 {
d.Set("project", parts[0])
d.SetId(parts[1])
return []*schema.ResourceData{d}, nil
} else {
return nil, fmt.Errorf("Invalid import id %q. Expecting {trigger_name} or {project}/{trigger_name}", d.Id())
}
}

View File

@ -4,50 +4,32 @@ import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
cloudbuild "google.golang.org/api/cloudbuild/v1"
)
func TestAccCloudBuildTrigger_basic(t *testing.T) {
t.Parallel()
projectID := "terraform-" + acctest.RandString(10)
projectOrg := getTestOrgFromEnv(t)
projectBillingAccount := getTestBillingAccountFromEnv(t)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGoogleCloudBuildTriggerVersionsDestroyed,
CheckDestroy: testAccCheckCloudbuildTriggerDestroy,
Steps: []resource.TestStep{
{
Config: testGoogleCloudBuildTrigger_basic(projectID, projectOrg, projectBillingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleCloudBuildTriggerExists("google_cloudbuild_trigger.build_trigger"),
),
Config: testGoogleCloudBuildTrigger_basic(),
},
{
ResourceName: "google_cloudbuild_trigger.build_trigger",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("%s/", projectID),
ResourceName: "google_cloudbuild_trigger.build_trigger",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testGoogleCloudBuildTrigger_updated(projectID, projectOrg, projectBillingAccount),
Config: testGoogleCloudBuildTrigger_updated(),
},
{
ResourceName: "google_cloudbuild_trigger.build_trigger",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("%s/", projectID),
},
{
Config: testGoogleCloudBuildTrigger_removed(projectID, projectOrg, projectBillingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleCloudBuildTriggerWasRemovedFromState("google_cloudbuild_trigger.build_trigger"),
),
ResourceName: "google_cloudbuild_trigger.build_trigger",
ImportState: true,
ImportStateVerify: true,
},
},
})
@ -56,147 +38,30 @@ func TestAccCloudBuildTrigger_basic(t *testing.T) {
func TestAccCloudBuildTrigger_filename(t *testing.T) {
t.Parallel()
projectID := "terraform-" + acctest.RandString(10)
projectOrg := getTestOrgFromEnv(t)
projectBillingAccount := getTestBillingAccountFromEnv(t)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGoogleCloudBuildTriggerVersionsDestroyed,
CheckDestroy: testAccCheckCloudbuildTriggerDestroy,
Steps: []resource.TestStep{
{
Config: testGoogleCloudBuildTrigger_filename(projectID, projectOrg, projectBillingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleCloudFilenameConfig("google_cloudbuild_trigger.filename_build_trigger"),
),
Config: testGoogleCloudBuildTrigger_filename(),
},
{
Config: testGoogleCloudBuildTrigger_removed(projectID, projectOrg, projectBillingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleCloudBuildTriggerWasRemovedFromState("google_cloudbuild_trigger.filename_build_trigger"),
),
ResourceName: "google_cloudbuild_trigger.filename_build_trigger",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccGetBuildTrigger(s *terraform.State, resourceName string) (*cloudbuild.BuildTrigger, error) {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return nil, fmt.Errorf("Resource not found: %s", resourceName)
}
if rs.Primary.ID == "" {
return nil, fmt.Errorf("No ID is set")
}
config := testAccProvider.Meta().(*Config)
project := rs.Primary.Attributes["project"]
trigger, err := config.clientBuild.Projects.Triggers.Get(project, rs.Primary.ID).Do()
if err != nil {
return nil, fmt.Errorf("Trigger does not exist")
}
return trigger, nil
}
func testAccCheckGoogleCloudBuildTriggerExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, err := testAccGetBuildTrigger(s, resourceName)
if err != nil {
return fmt.Errorf("Trigger does not exist")
}
return nil
}
}
func testAccCheckGoogleCloudFilenameConfig(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
trigger, err := testAccGetBuildTrigger(s, resourceName)
if err != nil {
return fmt.Errorf("Trigger does not exist")
}
if trigger.Filename != "cloudbuild.yaml" {
return fmt.Errorf("Config filename mismatch: %s", trigger.Filename)
}
return nil
}
}
func testAccCheckGoogleCloudBuildTriggerWasRemovedFromState(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[resourceName]
if ok {
return fmt.Errorf("Resource was not removed from state: %s", resourceName)
}
return nil
}
}
func testAccCheckGoogleCloudBuildTriggerVersionsDestroyed(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
for _, rs := range s.RootModule().Resources {
if rs.Type != "google_cloudbuild_trigger" {
continue
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
project := rs.Primary.Attributes["project"]
_, err := config.clientBuild.Projects.Triggers.Get(project, rs.Primary.ID).Do()
if err == nil {
return fmt.Errorf("Trigger still exists")
}
}
return nil
}
/*
This test runs in its own project, otherwise the test project would start to get filled
with undeletable resources
*/
func testGoogleCloudBuildTrigger_basic(projectID, projectOrg, projectBillingAccount string) string {
func testGoogleCloudBuildTrigger_basic() string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}
resource "google_project_services" "acceptance" {
project = "${google_project.acceptance.project_id}"
services = [
"cloudbuild.googleapis.com",
"containerregistry.googleapis.com",
"logging.googleapis.com",
"pubsub.googleapis.com",
"storage-api.googleapis.com",
]
}
resource "google_cloudbuild_trigger" "build_trigger" {
project = "${google_project_services.acceptance.project}"
description = "acceptance test build trigger"
trigger_template {
branch_name = "master"
project = "${google_project_services.acceptance.project}"
repo_name = "some-repo"
}
build {
@ -204,48 +69,27 @@ resource "google_cloudbuild_trigger" "build_trigger" {
tags = ["team-a", "service-b"]
step {
name = "gcr.io/cloud-builders/gsutil"
args = "cp gs://mybucket/remotefile.zip localfile.zip "
args = ["cp", "gs://mybucket/remotefile.zip", "localfile.zip"]
}
step {
name = "gcr.io/cloud-builders/go"
args = "build my_package"
args = ["build", "my_package"]
}
step {
name = "gcr.io/cloud-builders/docker"
args = "build -t gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA -f Dockerfile ."
args = ["build", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA", "-f", "Dockerfile", "."]
}
}
}
`, projectID, projectID, projectOrg, projectBillingAccount)
`)
}
func testGoogleCloudBuildTrigger_updated(projectID, projectOrg, projectBillingAccount string) string {
func testGoogleCloudBuildTrigger_updated() string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}
resource "google_project_services" "acceptance" {
project = "${google_project.acceptance.project_id}"
services = [
"cloudbuild.googleapis.com",
"containerregistry.googleapis.com",
"logging.googleapis.com",
"pubsub.googleapis.com",
"storage-api.googleapis.com",
]
}
resource "google_cloudbuild_trigger" "build_trigger" {
project = "${google_project_services.acceptance.project}"
description = "acceptance test build trigger updated"
trigger_template {
branch_name = "master-updated"
project = "${google_project_services.acceptance.project}"
repo_name = "some-repo-updated"
}
build {
@ -253,48 +97,28 @@ resource "google_cloudbuild_trigger" "build_trigger" {
tags = ["team-a", "service-b", "updated"]
step {
name = "gcr.io/cloud-builders/gsutil"
args = "cp gs://mybucket/remotefile.zip localfile-updated.zip "
args = ["cp", "gs://mybucket/remotefile.zip", "localfile-updated.zip"]
}
step {
name = "gcr.io/cloud-builders/go"
args = "build my_package_updated"
args = ["build", "my_package_updated"]
}
step {
name = "gcr.io/cloud-builders/docker"
args = "build -t gcr.io/$PROJECT_ID/$REPO_NAME:$SHORT_SHA -f Dockerfile ."
args = ["build", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:$SHORT_SHA", "-f", "Dockerfile", "."]
}
step {
name = "gcr.io/$PROJECT_ID/$REPO_NAME:$SHORT_SHA"
args = "test"
args = ["test"]
}
}
}
`, projectID, projectID, projectOrg, projectBillingAccount)
`)
}
func testGoogleCloudBuildTrigger_filename(projectID, projectOrg, projectBillingAccount string) string {
func testGoogleCloudBuildTrigger_filename() string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}
resource "google_project_services" "acceptance" {
project = "${google_project.acceptance.project_id}"
services = [
"cloudbuild.googleapis.com",
"containerregistry.googleapis.com",
"logging.googleapis.com",
"pubsub.googleapis.com",
"storage-api.googleapis.com",
]
}
resource "google_cloudbuild_trigger" "filename_build_trigger" {
project = "${google_project_services.acceptance.project}"
description = "acceptance test build trigger"
trigger_template {
branch_name = "master"
@ -306,28 +130,5 @@ resource "google_cloudbuild_trigger" "filename_build_trigger" {
}
filename = "cloudbuild.yaml"
}
`, projectID, projectID, projectOrg, projectBillingAccount)
}
func testGoogleCloudBuildTrigger_removed(projectID, projectOrg, projectBillingAccount string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}
resource "google_project_services" "acceptance" {
project = "${google_project.acceptance.project_id}"
services = [
"cloudbuild.googleapis.com",
"containerregistry.googleapis.com",
"logging.googleapis.com",
"pubsub.googleapis.com",
"storage-api.googleapis.com",
]
}
`, projectID, projectID, projectOrg, projectBillingAccount)
`)
}

View File

@ -0,0 +1,730 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import (
"fmt"
"log"
"reflect"
"time"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceCloudbuildTrigger() *schema.Resource {
return &schema.Resource{
Create: resourceCloudbuildTriggerCreate,
Read: resourceCloudbuildTriggerRead,
Update: resourceCloudbuildTriggerUpdate,
Delete: resourceCloudbuildTriggerDelete,
Importer: &schema.ResourceImporter{
State: resourceCloudbuildTriggerImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Update: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
},
SchemaVersion: 1,
Schema: map[string]*schema.Schema{
"build": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"images": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"step": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"args": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"name": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"tags": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
ConflictsWith: []string{"filename"},
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"disabled": {
Type: schema.TypeString,
Optional: true,
},
"filename": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"build"},
},
"ignored_files": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"included_files": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"substitutions": {
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"trigger_template": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"branch_name": {
Type: schema.TypeString,
Optional: true,
},
"commit_sha": {
Type: schema.TypeString,
Optional: true,
},
"dir": {
Type: schema.TypeString,
Optional: true,
},
"project_id": {
Type: schema.TypeString,
Computed: true,
Optional: true,
},
"repo_name": {
Type: schema.TypeString,
Optional: true,
Default: "default",
},
"tag_name": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"create_time": {
Type: schema.TypeString,
Computed: true,
},
"trigger_id": {
Type: schema.TypeString,
Computed: true,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
}
}
func resourceCloudbuildTriggerCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
obj := make(map[string]interface{})
descriptionProp, err := expandCloudbuildTriggerDescription(d.Get("description"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
obj["description"] = descriptionProp
}
disabledProp, err := expandCloudbuildTriggerDisabled(d.Get("disabled"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("disabled"); !isEmptyValue(reflect.ValueOf(disabledProp)) && (ok || !reflect.DeepEqual(v, disabledProp)) {
obj["disabled"] = disabledProp
}
substitutionsProp, err := expandCloudbuildTriggerSubstitutions(d.Get("substitutions"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("substitutions"); !isEmptyValue(reflect.ValueOf(substitutionsProp)) && (ok || !reflect.DeepEqual(v, substitutionsProp)) {
obj["substitutions"] = substitutionsProp
}
filenameProp, err := expandCloudbuildTriggerFilename(d.Get("filename"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("filename"); !isEmptyValue(reflect.ValueOf(filenameProp)) && (ok || !reflect.DeepEqual(v, filenameProp)) {
obj["filename"] = filenameProp
}
ignoredFilesProp, err := expandCloudbuildTriggerIgnoredFiles(d.Get("ignored_files"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("ignored_files"); !isEmptyValue(reflect.ValueOf(ignoredFilesProp)) && (ok || !reflect.DeepEqual(v, ignoredFilesProp)) {
obj["ignoredFiles"] = ignoredFilesProp
}
includedFilesProp, err := expandCloudbuildTriggerIncludedFiles(d.Get("included_files"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("included_files"); !isEmptyValue(reflect.ValueOf(includedFilesProp)) && (ok || !reflect.DeepEqual(v, includedFilesProp)) {
obj["includedFiles"] = includedFilesProp
}
triggerTemplateProp, err := expandCloudbuildTriggerTriggerTemplate(d.Get("trigger_template"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("trigger_template"); !isEmptyValue(reflect.ValueOf(triggerTemplateProp)) && (ok || !reflect.DeepEqual(v, triggerTemplateProp)) {
obj["triggerTemplate"] = triggerTemplateProp
}
buildProp, err := expandCloudbuildTriggerBuild(d.Get("build"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("build"); !isEmptyValue(reflect.ValueOf(buildProp)) && (ok || !reflect.DeepEqual(v, buildProp)) {
obj["build"] = buildProp
}
url, err := replaceVars(d, config, "https://cloudbuild.googleapis.com/v1/projects/{{project}}/triggers")
if err != nil {
return err
}
log.Printf("[DEBUG] Creating new Trigger: %#v", obj)
res, err := sendRequestWithTimeout(config, "POST", url, obj, d.Timeout(schema.TimeoutCreate))
if err != nil {
return fmt.Errorf("Error creating Trigger: %s", err)
}
// Store the ID now
id, err := replaceVars(d, config, "{{project}}/{{trigger_id}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
log.Printf("[DEBUG] Finished creating Trigger %q: %#v", d.Id(), res)
// `name` is autogenerated from the api so needs to be set post-create
triggerId, ok := res["id"]
if !ok {
return fmt.Errorf("Create response didn't contain id. Create may not have succeeded.")
}
d.Set("trigger_id", triggerId.(string))
// Store the ID now. We tried to set it before and it failed because
// trigger_id didn't exist yet.
id, err = replaceVars(d, config, "{{project}}/{{trigger_id}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return resourceCloudbuildTriggerRead(d, meta)
}
func resourceCloudbuildTriggerRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
url, err := replaceVars(d, config, "https://cloudbuild.googleapis.com/v1/projects/{{project}}/triggers/{{trigger_id}}")
if err != nil {
return err
}
res, err := sendRequest(config, "GET", url, nil)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("CloudbuildTrigger %q", d.Id()))
}
project, err := getProject(d, config)
if err != nil {
return err
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("trigger_id", flattenCloudbuildTriggerTrigger_id(res["id"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("description", flattenCloudbuildTriggerDescription(res["description"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("disabled", flattenCloudbuildTriggerDisabled(res["disabled"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("create_time", flattenCloudbuildTriggerCreateTime(res["createTime"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("substitutions", flattenCloudbuildTriggerSubstitutions(res["substitutions"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("filename", flattenCloudbuildTriggerFilename(res["filename"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("ignored_files", flattenCloudbuildTriggerIgnoredFiles(res["ignoredFiles"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("included_files", flattenCloudbuildTriggerIncludedFiles(res["includedFiles"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("trigger_template", flattenCloudbuildTriggerTriggerTemplate(res["triggerTemplate"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
if err := d.Set("build", flattenCloudbuildTriggerBuild(res["build"], d)); err != nil {
return fmt.Errorf("Error reading Trigger: %s", err)
}
return nil
}
func resourceCloudbuildTriggerUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
obj := make(map[string]interface{})
descriptionProp, err := expandCloudbuildTriggerDescription(d.Get("description"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
obj["description"] = descriptionProp
}
disabledProp, err := expandCloudbuildTriggerDisabled(d.Get("disabled"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("disabled"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, disabledProp)) {
obj["disabled"] = disabledProp
}
substitutionsProp, err := expandCloudbuildTriggerSubstitutions(d.Get("substitutions"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("substitutions"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, substitutionsProp)) {
obj["substitutions"] = substitutionsProp
}
filenameProp, err := expandCloudbuildTriggerFilename(d.Get("filename"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("filename"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, filenameProp)) {
obj["filename"] = filenameProp
}
triggerTemplateProp, err := expandCloudbuildTriggerTriggerTemplate(d.Get("trigger_template"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("trigger_template"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, triggerTemplateProp)) {
obj["triggerTemplate"] = triggerTemplateProp
}
buildProp, err := expandCloudbuildTriggerBuild(d.Get("build"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("build"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, buildProp)) {
obj["build"] = buildProp
}
url, err := replaceVars(d, config, "https://cloudbuild.googleapis.com/v1/projects/{{project}}/triggers/{{trigger_id}}")
if err != nil {
return err
}
log.Printf("[DEBUG] Updating Trigger %q: %#v", d.Id(), obj)
obj["id"] = d.Get("trigger_id")
_, err = sendRequestWithTimeout(config, "PATCH", url, obj, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("Error updating Trigger %q: %s", d.Id(), err)
}
return resourceCloudbuildTriggerRead(d, meta)
}
func resourceCloudbuildTriggerDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
url, err := replaceVars(d, config, "https://cloudbuild.googleapis.com/v1/projects/{{project}}/triggers/{{trigger_id}}")
if err != nil {
return err
}
var obj map[string]interface{}
log.Printf("[DEBUG] Deleting Trigger %q", d.Id())
res, err := sendRequestWithTimeout(config, "DELETE", url, obj, d.Timeout(schema.TimeoutDelete))
if err != nil {
return handleNotFoundError(err, d, "Trigger")
}
log.Printf("[DEBUG] Finished deleting Trigger %q: %#v", d.Id(), res)
return nil
}
func resourceCloudbuildTriggerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
if err := parseImportId([]string{"projects/(?P<project>[^/]+)/triggers/(?P<trigger_id>[^/]+)", "(?P<project>[^/]+)/(?P<trigger_id>[^/]+)", "(?P<trigger_id>[^/]+)"}, d, config); err != nil {
return nil, err
}
// Replace import id for the resource id
id, err := replaceVars(d, config, "{{project}}/{{trigger_id}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenCloudbuildTriggerTrigger_id(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerDescription(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerDisabled(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerCreateTime(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerSubstitutions(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerFilename(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerIgnoredFiles(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerIncludedFiles(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerTriggerTemplate(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["project_id"] =
flattenCloudbuildTriggerTriggerTemplateProjectId(original["projectId"], d)
transformed["repo_name"] =
flattenCloudbuildTriggerTriggerTemplateRepoName(original["repoName"], d)
transformed["dir"] =
flattenCloudbuildTriggerTriggerTemplateDir(original["dir"], d)
transformed["branch_name"] =
flattenCloudbuildTriggerTriggerTemplateBranchName(original["branchName"], d)
transformed["tag_name"] =
flattenCloudbuildTriggerTriggerTemplateTagName(original["tagName"], d)
transformed["commit_sha"] =
flattenCloudbuildTriggerTriggerTemplateCommitSha(original["commitSha"], d)
return []interface{}{transformed}
}
func flattenCloudbuildTriggerTriggerTemplateProjectId(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerTriggerTemplateRepoName(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerTriggerTemplateDir(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerTriggerTemplateBranchName(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerTriggerTemplateTagName(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerTriggerTemplateCommitSha(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerBuild(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["tags"] =
flattenCloudbuildTriggerBuildTags(original["tags"], d)
transformed["images"] =
flattenCloudbuildTriggerBuildImages(original["images"], d)
transformed["step"] =
flattenCloudbuildTriggerBuildStep(original["steps"], d)
return []interface{}{transformed}
}
func flattenCloudbuildTriggerBuildTags(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerBuildImages(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerBuildStep(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"name": flattenCloudbuildTriggerBuildStepName(original["name"], d),
"args": flattenCloudbuildTriggerBuildStepArgs(original["args"], d),
})
}
return transformed
}
func flattenCloudbuildTriggerBuildStepName(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenCloudbuildTriggerBuildStepArgs(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func expandCloudbuildTriggerDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerDisabled(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerSubstitutions(v interface{}, d *schema.ResourceData, config *Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}
func expandCloudbuildTriggerFilename(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerIgnoredFiles(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerIncludedFiles(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerTriggerTemplate(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedProjectId, err := expandCloudbuildTriggerTriggerTemplateProjectId(original["project_id"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedProjectId); val.IsValid() && !isEmptyValue(val) {
transformed["projectId"] = transformedProjectId
}
transformedRepoName, err := expandCloudbuildTriggerTriggerTemplateRepoName(original["repo_name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRepoName); val.IsValid() && !isEmptyValue(val) {
transformed["repoName"] = transformedRepoName
}
transformedDir, err := expandCloudbuildTriggerTriggerTemplateDir(original["dir"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedDir); val.IsValid() && !isEmptyValue(val) {
transformed["dir"] = transformedDir
}
transformedBranchName, err := expandCloudbuildTriggerTriggerTemplateBranchName(original["branch_name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedBranchName); val.IsValid() && !isEmptyValue(val) {
transformed["branchName"] = transformedBranchName
}
transformedTagName, err := expandCloudbuildTriggerTriggerTemplateTagName(original["tag_name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedTagName); val.IsValid() && !isEmptyValue(val) {
transformed["tagName"] = transformedTagName
}
transformedCommitSha, err := expandCloudbuildTriggerTriggerTemplateCommitSha(original["commit_sha"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedCommitSha); val.IsValid() && !isEmptyValue(val) {
transformed["commitSha"] = transformedCommitSha
}
return transformed, nil
}
func expandCloudbuildTriggerTriggerTemplateProjectId(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerTriggerTemplateRepoName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerTriggerTemplateDir(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerTriggerTemplateBranchName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerTriggerTemplateTagName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerTriggerTemplateCommitSha(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerBuild(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedTags, err := expandCloudbuildTriggerBuildTags(original["tags"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedTags); val.IsValid() && !isEmptyValue(val) {
transformed["tags"] = transformedTags
}
transformedImages, err := expandCloudbuildTriggerBuildImages(original["images"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedImages); val.IsValid() && !isEmptyValue(val) {
transformed["images"] = transformedImages
}
transformedStep, err := expandCloudbuildTriggerBuildStep(original["step"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedStep); val.IsValid() && !isEmptyValue(val) {
transformed["steps"] = transformedStep
}
return transformed, nil
}
func expandCloudbuildTriggerBuildTags(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerBuildImages(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerBuildStep(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedName, err := expandCloudbuildTriggerBuildStepName(original["name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) {
transformed["name"] = transformedName
}
transformedArgs, err := expandCloudbuildTriggerBuildStepArgs(original["args"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedArgs); val.IsValid() && !isEmptyValue(val) {
transformed["args"] = transformedArgs
}
req = append(req, transformed)
}
return req, nil
}
func expandCloudbuildTriggerBuildStepName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandCloudbuildTriggerBuildStepArgs(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}

View File

@ -0,0 +1,92 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccCloudbuildTrigger_cloudbuildTriggerFilenameExample(t *testing.T) {
t.Parallel()
context := map[string]interface{}{
"random_suffix": acctest.RandString(10),
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudbuildTriggerDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudbuildTrigger_cloudbuildTriggerFilenameExample(context),
},
{
ResourceName: "google_cloudbuild_trigger.filename-trigger",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccCloudbuildTrigger_cloudbuildTriggerFilenameExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_cloudbuild_trigger" "filename-trigger" {
trigger_template {
branch_name = "master"
repo_name = "my-repo"
}
substitutions = {
_FOO = "bar"
_BAZ = "qux"
}
filename = "cloudbuild.yaml"
}
`, context)
}
func testAccCheckCloudbuildTriggerDestroy(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
if rs.Type != "google_cloudbuild_trigger" {
continue
}
if strings.HasPrefix(name, "data.") {
continue
}
config := testAccProvider.Meta().(*Config)
url, err := replaceVarsForTest(rs, "https://cloudbuild.googleapis.com/v1/projects/{{project}}/triggers/{{trigger_id}}")
if err != nil {
return err
}
_, err = sendRequest(config, "GET", url, nil)
if err == nil {
return fmt.Errorf("CloudbuildTrigger still exists at %s", url)
}
}
return nil
}

View File

@ -212,19 +212,6 @@ func expandEnvironmentVariables(d *schema.ResourceData) map[string]string {
return expandStringMap(d, "environment_variables")
}
// expandStringSlice pulls the value of key out of schema.ResourceData as a []string
func expandStringSlice(d *schema.ResourceData, key string) []string {
var strings []string
if interfaceStrings, ok := d.GetOk(key); ok {
for _, str := range interfaceStrings.([]interface{}) {
strings = append(strings, str.(string))
}
}
return strings
}
// expandStringMap pulls the value of key out of a schema.ResourceData as a map[string]string.
func expandStringMap(d *schema.ResourceData, key string) map[string]string {
v, ok := d.GetOk(key)

View File

@ -1,157 +1,223 @@
---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google"
page_title: "Google: google_cloudbuild_trigger"
sidebar_current: "docs-google-cloudbuild-trigger"
description: |-
Creates a new build trigger within GCR.
Configuration for an automated build in response to source repository changes.
---
# google\_cloudbuild\_trigger
Creates a new build trigger within GCR. For more information, see
[the official documentation](https://cloud.google.com/container-builder/docs/running-builds/automate-builds)
and
[API](https://godoc.org/google.golang.org/api/cloudbuild/v1#BuildTrigger).
Configuration for an automated build in response to source repository changes.
To get more information about Trigger, see:
* [API documentation](https://cloud.google.com/cloud-build/docs/api/reference/rest/)
* How-to Guides
* [Automating builds using build triggers](https://cloud.google.com/cloud-build/docs/running-builds/automate-builds)
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_working_dir=cloudbuild_trigger_filename&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
</a>
</div>
## Example Usage - Cloudbuild Trigger Filename
## Example Usage
```hcl
resource "google_cloudbuild_trigger" "build_trigger" {
project = "my-project"
resource "google_cloudbuild_trigger" "filename-trigger" {
trigger_template {
branch_name = "master"
project = "my-project"
repo_name = "some-repo"
repo_name = "my-repo"
}
build {
images = ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"]
step {
name = "gcr.io/cloud-builders/docker"
args = "build -t gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA -f Dockerfile ."
}
}
}
```
OR
```hcl
resource "google_cloudbuild_trigger" "build_trigger" {
project = "my-project"
trigger_template {
branch_name = "master"
project = "my-project"
repo_name = "some-repo"
substitutions = {
_FOO = "bar"
_BAZ = "qux"
}
filename = "cloudbuild.yaml"
}
```
## Argument Reference
(Argument descriptions sourced from https://godoc.org/google.golang.org/api/cloudbuild/v1#BuildTrigger)
The following arguments are supported:
* `build` - (Optional) A build resource in the Container Builder API.
Structure is documented below. At a high
level, a `build` describes where to find source code, how to build it (for
example, the builder image to run on the source), and where to store
the built artifacts. Fields can include the following variables, which
will be expanded when the build is created:
* `$PROJECT_ID`: the project ID of the build.
* `$BUILD_ID`: the autogenerated ID of the build.
* `$REPO_NAME`: the source repository name specified by RepoSource.
* `$BRANCH_NAME`: the branch name specified by RepoSource.
* `$TAG_NAME`: the tag name specified by RepoSource.
* `$REVISION_ID` or `$COMMIT_SHA`: the commit SHA specified by RepoSource
or resolved from the specified branch or tag.
* `$SHORT_SHA`: first 7 characters of `$REVISION_ID` or `$COMMIT_SHA`.
* `description` - (Optional) A brief description of this resource.
* `ignored_files` - (Optional) `ignored_files` and `included_files` are file glob matches using http://godoc/pkg/path/filepath#Match extended with support for "\*\*". If `ignored_files` and changed files are both empty, then they are not used to determine whether or not to trigger a build. If `ignored_files` is not empty, then we ignore any files that match any of the ignored_file globs. If the change has no files that are outside of the `ignored_files` globs, then
we do not trigger a build.
- - -
* `included_files` - (Optional) If any of the files altered in the commit pass the `ignored_files` filter and `included_files` is empty, then as far as this filter is concerned, we should trigger the build. If any of the files altered in the commit pass the `ignored_files` filter and `included_files` is not empty, then we make sure that at least one of those files matches a `included_files` glob. If not, then we do not trigger a build.
* `filename` - (Optional) Specify the path to a Cloud Build configuration file
in the Git repo. This is mutually exclusive with `build`. This is typically
`cloudbuild.yaml` however it can be specified by the user.
* `description` -
(Optional)
Human-readable description of the trigger.
* `project` - (Optional) The ID of the project that the trigger will be created in.
Defaults to the provider project configuration.
* `disabled` -
(Optional)
Whether the trigger is disabled or not. If true, the trigger will never result in a build.
* `substitutions`: (Optional) User-defined substitutions.
User-defined substitutions must conform to the following rules:
* Substitutions must begin with an underscore (`_`) and use only
uppercase-letters and numbers (respecting the regular expression
`_[A-Z0-9_]+`). This prevents conflicts with built-in substitutions.
* Unmatched keys in the template will cause an error (for example, if a build
request includes `$_FOO` and the substitutions map doesnt define `_FOO`).
* Unmatched keys in the parameters list will result in an error (for example,
if a substitutions map defines `_FOO` but the build request doesn't include `$_FOO`).
* To include a literal `$_VARIABLE` in the template, you must escape with `$$`.
* You can explicitly denote variable expansion using the `${_VAR}` syntax. This prevents
ambiguity in cases like `${_FOO}BAR`, where `$_FOO` is a variable.
* The number of parameters is limited to 100 parameters.
* The length of a parameter key and the length of a parameter value
are limited to 100 characters.
* `substitutions` -
(Optional)
Substitutions data for Build resource.
* `trigger_template` - (Optional) Location of the source in a Google
Cloud Source Repository. Structure is documented below.
* `filename` -
(Optional)
Path, from the source root, to a file whose contents is used for the template.
---
* `ignored_files` -
(Optional)
ignoredFiles and includedFiles are file glob matches using http://godoc/pkg/path/filepath#Match
extended with support for "**".
If ignoredFiles and changed files are both empty, then they are not
used to determine whether or not to trigger a build.
If ignoredFiles is not empty, then we ignore any files that match any
of the ignored_file globs. If the change has no files that are outside
of the ignoredFiles globs, then we do not trigger a build.
The `build` block supports:
* `included_files` -
(Optional)
ignoredFiles and includedFiles are file glob matches using http://godoc/pkg/path/filepath#Match
extended with support for "**".
If any of the files altered in the commit pass the ignoredFiles filter
and includedFiles is empty, then as far as this filter is concerned, we
should trigger the build.
If any of the files altered in the commit pass the ignoredFiles filter
and includedFiles is not empty, then we make sure that at least one of
those files matches a includedFiles glob. If not, then we do not trigger
a build.
* `images` - (Optional) A list of images to be pushed upon the successful
completion of all build steps.
* `trigger_template` -
(Optional)
Template describing the types of source changes to trigger a build.
Branch and tag names in trigger templates are interpreted as regular
expressions. Any branch or tag change that matches that regular
expression will trigger a build. Structure is documented below.
* `step` - (Optional) The operations to be performed on the workspace.
Structure is documented below.
* `build` -
(Optional)
Contents of the build template. Structure is documented below.
* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
* `tags` - (Optional) Tags for annotation of a build. **These are not docker tags**
---
The `step` block supports:
* `name` - (Optional) The name of the container image that will run this
particular build step. If the image is available in the host's Docker
daemon's cache, it will be run directly. If not, the host will attempt to
pull the image first, using the builder service account's credentials if
necessary. The Docker daemon's cache will already have the latest versions
of all of the officially supported build steps
(https://github.com/GoogleCloudPlatform/cloud-builders).
The Docker daemon will also have cached many of the layers for some popular
images, like "ubuntu", "debian", but they will be refreshed at the time you
attempt to use them. If you built an image in a previous build step, it will
be stored in the host's Docker daemon's cache and is available to use as
the name for a later build step.
* `args` - (Optional) A list of arguments that will be presented to the step
when it is started. If the image used to run the step's container has an
entrypoint, the `args` are used as arguments to that entrypoint. If the image
does not define an entrypoint, the first element in args is used as the
entrypoint, and the remainder will be used as arguments.
---
The `trigger_template` block supports:
* `branch_name` - (Optional) Name of the branch to build.
* `project_id` -
(Optional)
ID of the project that owns the Cloud Source Repository. If
omitted, the project ID requesting the build is assumed.
* `commit_sha` - (Optional) Explicit commit SHA to build.
* `repo_name` -
(Optional)
Name of the Cloud Source Repository. If omitted, the name "default" is assumed.
* `dir` - (Optional) Directory, relative to the source root, in which to run
the build. This must be a relative path. If a step's `dir` is specified and
is an absolute path, this value is ignored for that step's execution.
* `dir` -
(Optional)
Directory, relative to the source root, in which to run the build.
This must be a relative path. If a step's dir is specified and
is an absolute path, this value is ignored for that step's
execution.
* `project` - (Optional) ID of the project that owns the Cloud Source Repository.
* `branch_name` -
(Optional)
Name of the branch to build.
* `repo_name` - (Optional) Name of the Cloud Source Repository.
* `tag_name` -
(Optional)
Name of the tag to build.
* `tag_name` - (Optional) Name of the tag to build.
* `commit_sha` -
(Optional)
Explicit commit SHA to build.
The `build` block supports:
* `tags` -
(Optional)
Tags for annotation of a Build. These are not docker tags.
* `images` -
(Optional)
A list of images to be pushed upon the successful completion of all build steps.
The images are pushed using the builder service account's credentials.
The digests of the pushed images will be stored in the Build resource's results field.
If any of the images fail to be pushed, the build status is marked FAILURE.
* `step` -
(Optional)
The operations to be performed on the workspace. Structure is documented below.
The `step` block supports:
* `name` -
(Optional)
The name of the container image that will run this particular build step.
If the image is available in the host's Docker daemon's cache, it will be
run directly. If not, the host will attempt to pull the image first, using
the builder service account's credentials if necessary.
The Docker daemon's cache will already have the latest versions of all of
the officially supported build steps (https://github.com/GoogleCloudPlatform/cloud-builders).
The Docker daemon will also have cached many of the layers for some popular
images, like "ubuntu", "debian", but they will be refreshed at the time
you attempt to use them.
If you built an image in a previous build step, it will be stored in the
host's Docker daemon's cache and is available to use as the name for a
later build step.
* `args` -
(Optional)
A list of arguments that will be presented to the step when it is started.
If the image used to run the step's container has an entrypoint, the args
are used as arguments to that entrypoint. If the image does not define an
entrypoint, the first element in args is used as the entrypoint, and the
remainder will be used as arguments.
## Attributes Reference
In addition to the arguments listed above, the following computed attributes are exported:
* `trigger_id` -
The unique identifier for the trigger.
* `create_time` -
Time when the trigger was created.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `update` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import
Trigger can be imported using any of these accepted formats:
```
$ terraform import google_cloudbuild_trigger.default projects/{{project}}/triggers/{{trigger_id}}
$ terraform import google_cloudbuild_trigger.default {{project}}/{{trigger_id}}
$ terraform import google_cloudbuild_trigger.default {{trigger_id}}
```
-> If you're importing a resource with beta features, make sure to include `-provider=google-beta`
as an argument so that Terraform uses the correct provider to import your resource.