Created
February 28, 2018 16:36
-
-
Save justinholmes/af62356ebd485e4b63e1e3153baef392 to your computer and use it in GitHub Desktop.
Cloudbuild trigger provider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package google | |
import ( | |
"fmt" | |
"github.com/hashicorp/terraform/helper/schema" | |
"google.golang.org/api/cloudbuild/v1" | |
"log" | |
"strings" | |
) | |
func resourceCloudbuildTrigger() *schema.Resource { | |
return &schema.Resource{ | |
Create: resourceCloudbuildTriggerCreate, | |
Read: resourceCloudbuildTriggerRead, | |
Delete: resourceCloudbuildTriggerDelete, | |
Update: resourceCloudbuildTriggerUpdate, | |
Schema: map[string]*schema.Schema{ | |
"project": { | |
Type: schema.TypeString, | |
Optional: true, | |
Computed: true, | |
ForceNew: true, | |
}, | |
"description": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"filename": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"substitutions": &schema.Schema{ | |
Type: schema.TypeMap, | |
Optional: true, | |
Elem: schema.TypeString, | |
}, | |
"disabled": &schema.Schema{ | |
Type: schema.TypeBool, | |
Optional: true, | |
}, | |
"trigger_template": &schema.Schema{ | |
Optional: true, | |
Type: schema.TypeList, | |
MaxItems: 1, | |
Elem: &schema.Resource{ | |
Schema: map[string]*schema.Schema{ | |
"branch_name": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"commit_sha": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"dir": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"project_id": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"repo_name": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"tag_name": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
}, | |
}, | |
}, | |
"build": &schema.Schema{ | |
Optional: true, | |
Type: schema.TypeList, | |
MaxItems: 1, | |
Elem: &schema.Resource{ | |
Schema: map[string]*schema.Schema{ | |
"images": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
"logs_bucket": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"options": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
MaxItems: 1, | |
Elem: &schema.Resource{ | |
Schema: map[string]*schema.Schema{ | |
"disk_size_gb": &schema.Schema{ | |
Type: schema.TypeInt, | |
Optional: true, | |
}, | |
"log_streaming_option": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"machine_type": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"requested_verify_option": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"source_provenance_hash": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
"substitution_option": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
}, | |
}, | |
}, | |
"secrets": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
MaxItems: 1, | |
Elem: &schema.Resource{ | |
Schema: map[string]*schema.Schema{ | |
"kms_key_name": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"secret_env": &schema.Schema{ | |
Type: schema.TypeMap, | |
Optional: true, | |
Elem: schema.TypeString, | |
}, | |
}, | |
}, | |
}, | |
"substitutions": &schema.Schema{ | |
Type: schema.TypeMap, | |
Optional: true, | |
Elem: schema.TypeString, | |
}, | |
"tags": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
"timeout": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"steps": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
MaxItems: 1, | |
Elem: &schema.Resource{ | |
Schema: map[string]*schema.Schema{ | |
"args": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
"dir": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"entrypoint": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"env": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
"id": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"name": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"secret_env": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
"volumes": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
MaxItems: 1, | |
Elem: &schema.Resource{ | |
Schema: map[string]*schema.Schema{ | |
"name": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
"path": &schema.Schema{ | |
Type: schema.TypeString, | |
Optional: true, | |
}, | |
}, | |
}, | |
}, | |
"wait_for": &schema.Schema{ | |
Type: schema.TypeList, | |
Optional: true, | |
Elem: &schema.Schema{Type: schema.TypeString}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
} | |
} | |
func resourceCloudbuildTriggerCreate(d *schema.ResourceData, meta interface{}) error { | |
config := meta.(*Config) | |
project, err := getProject(d, config) | |
if err != nil { | |
return err | |
} | |
buildTrigger := addOptionalFields(d) | |
trigger, err := config.clientCloudbuild.Projects.Triggers.Create(project, buildTrigger).Do() | |
if err != nil { | |
return fmt.Errorf("Error creating Cloudbuild Trigger: %s", err) | |
} | |
log.Printf("[INFO] Cloudbuild Trigger %s has been created", trigger.Id) | |
d.SetId(trigger.Id) | |
return resourceCloudbuildTriggerRead(d, meta) | |
} | |
func resourceCloudbuildTriggerRead(d *schema.ResourceData, meta interface{}) error { | |
config := meta.(*Config) | |
project, err := getProject(d, config) | |
if err != nil { | |
return err | |
} | |
Id := d.Id() | |
_, err = config.clientCloudbuild.Projects.Triggers.Get(project, Id).Do() | |
if err != nil { | |
return handleNotFoundError(err, d, fmt.Sprintf("Cloudbuild Trigger %q", Id)) | |
} | |
return nil | |
} | |
func addOptionalFields(d *schema.ResourceData) *cloudbuild.BuildTrigger { | |
buildTrigger := &cloudbuild.BuildTrigger{} | |
if v, ok := d.GetOk("description"); ok { | |
buildTrigger.Description = v.(string) | |
} | |
if v, ok := d.GetOk("filename"); ok { | |
buildTrigger.Filename = v.(string) | |
} | |
if v, ok := d.GetOk("disabled"); ok { | |
buildTrigger.Disabled = v.(bool) | |
} | |
if v, ok := d.Get("substitutions").(map[string]string); ok { | |
if (len(v)) > 0 { | |
buildTrigger.Substitutions = v | |
} | |
} | |
buildTrigger.TriggerTemplate = addTriggerTemplate(d) | |
buildTrigger.Build = addBuildTemplate(d) | |
return buildTrigger | |
} | |
func addTriggerTemplate(d *schema.ResourceData) *cloudbuild.RepoSource { | |
repoSource := &cloudbuild.RepoSource{} | |
if _triggerTemplate, ok := d.GetOk("trigger_template"); ok { | |
triggerTemplate := _triggerTemplate.([]interface{})[0].(map[string]interface{}) | |
if v, ok := triggerTemplate["branch_name"]; ok { | |
repoSource.BranchName = v.(string) | |
} | |
if v, ok := triggerTemplate["commit_sha"]; ok { | |
repoSource.CommitSha = v.(string) | |
} | |
if v, ok := triggerTemplate["dir"]; ok { | |
repoSource.Dir = v.(string) | |
} | |
if v, ok := triggerTemplate["project_id"]; ok { | |
repoSource.ProjectId = v.(string) | |
} | |
if v, ok := triggerTemplate["repo_name"]; ok { | |
repoSource.RepoName = v.(string) | |
} | |
if v, ok := triggerTemplate["tag_name"]; ok { | |
repoSource.TagName = v.(string) | |
} | |
} | |
return repoSource | |
} | |
func addBuildTemplate(d *schema.ResourceData) *cloudbuild.Build { | |
build := &cloudbuild.Build{} | |
if _buildSchema, ok := d.GetOk("build"); ok { | |
buildSchema := _buildSchema.([]interface{})[0].(map[string]interface{}) | |
if v, ok := buildSchema["logs_bucket"]; ok { | |
build.LogsBucket = v.(string) | |
} | |
build.Images = convertStringArr(buildSchema["images"].([]interface{})) | |
build.Tags = convertStringArr(buildSchema["tags"].([]interface{})) | |
var targetSubstitutions map[string]string | |
if v := buildSchema["substitutions"].(map[string]interface{}); len(v) > 0 { | |
targetSubstitutions = make(map[string]string, len(v)) | |
for k, v := range v { | |
targetSubstitutions[k] = v.(string) | |
} | |
} | |
build.Substitutions = targetSubstitutions | |
if v, ok := buildSchema["timeout"]; ok { | |
build.Timeout = v.(string) | |
} | |
if _secretsTemplate, ok := buildSchema["secrets"]; ok { | |
build.Secrets = addSecretsTemplate(_secretsTemplate) | |
} | |
if _optionsTemplate, ok := buildSchema["options"]; ok { | |
opts := _optionsTemplate.([]interface{}) | |
if len(opts) > 0 { | |
build.Options = addOptionsTemplate(opts) | |
} | |
} | |
if _stepsTemplate, ok := buildSchema["steps"]; ok { | |
build.Steps = addBuildStepsTemplate(_stepsTemplate) | |
} | |
if v, ok := buildSchema["timeout"].(string); ok { | |
if (len(v)) > 0 { | |
build.Timeout = v | |
} | |
} | |
} | |
return build | |
} | |
func addSecretsTemplate(_secretsTemplate interface{}) []*cloudbuild.Secret { | |
secretList := []*cloudbuild.Secret{} | |
_secrets := _secretsTemplate.([]interface{}) | |
for _, _secretTemplate := range _secrets { | |
var kmsKeyName string | |
secretTemplate := _secretTemplate.(map[string]interface{}) | |
if v, ok := secretTemplate["kms_key_name"]; ok { | |
kmsKeyName = v.(string) | |
} | |
secretEnvMap := make(map[string]string) | |
if v, ok := secretTemplate["secret_env"].(map[string]string); ok { | |
if (len(v)) > 0 { | |
secretEnvMap = v | |
} | |
} | |
if len(strings.TrimSpace(kmsKeyName)) != 0 { | |
secret := new(cloudbuild.Secret) | |
secret.KmsKeyName = kmsKeyName | |
secret.SecretEnv = secretEnvMap | |
secretList = append(secretList, secret) | |
} | |
} | |
return secretList | |
} | |
func addOptionsTemplate(_optionsTemplate []interface{}) *cloudbuild.BuildOptions { | |
buildOptions := new(cloudbuild.BuildOptions) | |
options := _optionsTemplate[0].(map[string]interface{}) | |
if v, ok := options["disk_size_gb"]; ok { | |
buildOptions.DiskSizeGb = int64(v.(int)) | |
} | |
if v, ok := options["log_streaming_option"]; ok { | |
buildOptions.LogStreamingOption = v.(string) | |
} | |
if v, ok := options["machine_type"]; ok { | |
buildOptions.MachineType = v.(string) | |
} | |
if v, ok := options["requested_verify_option"]; ok { | |
buildOptions.RequestedVerifyOption = v.(string) | |
} | |
var targetSourceProvenanceHash []string | |
if v := options["source_provenance_hash"].([]string); len(v) > 0 { | |
for i, v := range v { | |
targetSourceProvenanceHash[i] = v | |
} | |
} | |
buildOptions.SourceProvenanceHash = targetSourceProvenanceHash | |
if v, ok := options["substitution_option"]; ok { | |
buildOptions.SubstitutionOption = v.(string) | |
} | |
return buildOptions | |
} | |
func addBuildStepsTemplate(_stepsTemplate interface{}) []*cloudbuild.BuildStep { | |
stepList := []*cloudbuild.BuildStep{} | |
_steps := _stepsTemplate.([]interface{}) | |
for _, _stepTemplate := range _steps { | |
stepTemplate := _stepTemplate.(map[string]interface{}) | |
buildStep := new(cloudbuild.BuildStep) | |
buildStep.Args = convertStringArr(stepTemplate["args"].([]interface{})) | |
if v, ok := stepTemplate["dir"]; ok { | |
buildStep.Dir = v.(string) | |
} | |
if v, ok := stepTemplate["entrypoint"]; ok { | |
buildStep.Entrypoint = v.(string) | |
} | |
buildStep.Env = convertStringArr(stepTemplate["env"].([]interface{})) | |
if v, ok := stepTemplate["id"]; ok { | |
buildStep.Id = v.(string) | |
} | |
if v, ok := stepTemplate["name"]; ok { | |
buildStep.Name = v.(string) | |
} | |
buildStep.SecretEnv = convertStringArr(stepTemplate["secret_env"].([]interface{})) | |
if _volumesTemplate, ok := stepTemplate["volumes"]; ok { | |
buildStep.Volumes = addVolumesTemplate(_volumesTemplate) | |
} | |
buildStep.WaitFor = convertStringArr(stepTemplate["wait_for"].([]interface{})) | |
stepList = append(stepList, buildStep) | |
} | |
return stepList | |
} | |
func addVolumesTemplate(_volumesTemplate interface{}) []*cloudbuild.Volume { | |
volumeList := []*cloudbuild.Volume{} | |
_volumes := _volumesTemplate.([]interface{}) | |
for _, _volumeTemplate := range _volumes { | |
volumeTemplate := _volumeTemplate.(map[string]interface{}) | |
volume := new(cloudbuild.Volume) | |
if v, ok := volumeTemplate["name"]; ok { | |
volume.Name = v.(string) | |
} | |
if v, ok := volumeTemplate["path"]; ok { | |
volume.Path = v.(string) | |
} | |
volumeList = append(volumeList, volume) | |
} | |
return volumeList | |
} | |
func resourceCloudbuildTriggerDelete(d *schema.ResourceData, meta interface{}) error { | |
config := meta.(*Config) | |
project, err := getProject(d, config) | |
if err != nil { | |
return err | |
} | |
_, err = config.clientCloudbuild.Projects.Triggers.Delete(project, d.Id()).Do() | |
if err != nil { | |
return fmt.Errorf("Error deleting Cloudbuild Trigger: %s", err) | |
} | |
d.SetId("") | |
return err | |
} | |
func resourceCloudbuildTriggerUpdate(d *schema.ResourceData, meta interface{}) error { | |
config := meta.(*Config) | |
project, err := getProject(d, config) | |
if err != nil { | |
return err | |
} | |
buildTrigger := addOptionalFields(d) | |
_, err = config.clientCloudbuild.Projects.Triggers.Patch(project, d.Id(), buildTrigger).Do() | |
if err != nil { | |
return fmt.Errorf("Error updating Cloudbuild Trigger: %s", err) | |
} | |
return resourceCloudbuildTriggerRead(d, meta) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment