diff --git a/env0/resource_template.go b/env0/resource_template.go index 46cf1ef7..dc1fd448 100644 --- a/env0/resource_template.go +++ b/env0/resource_template.go @@ -4,59 +4,14 @@ import ( "context" "errors" "log" - "sort" "github.com/env0/terraform-provider-env0/client" "github.com/google/uuid" - "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func resourceTemplate() *schema.Resource { - validateRetries := func(i interface{}, path cty.Path) diag.Diagnostics { - retries := i.(int) - if retries < 1 || retries > 3 { - return diag.Errorf("Retries amount must be between 1 and 3") - } - - return nil - } - - /* - * VCS Constraints: - * GitHub - githubInstallationId - * GitLab - gitlabProjectId and tokenId - * Bitbucket - bitbucketClientKey - * GH Enterprise - isGitHubEnterprise - * GL Enterprise - isGitLabEnterprise - * BB Server - isBitbucketServer - * Other - tokenId (optional field) - */ - - allVCSAttributes := []string{ - "token_id", - "gitlab_project_id", - "github_installation_id", - "bitbucket_client_key", - "is_gitlab_enterprise", - "is_bitbucket_server", - "is_github_enterprise", - } - - allVCSAttributesBut := func(strs ...string) []string { - sort.Strings(strs) - ret := []string{} - - for _, attr := range allVCSAttributes { - if sort.SearchStrings(strs, attr) >= len(strs) { - ret = append(ret, attr) - } - } - - return ret - } - return &schema.Resource{ CreateContext: resourceTemplateCreate, ReadContext: resourceTemplateRead, @@ -65,131 +20,7 @@ func resourceTemplate() *schema.Resource { Importer: &schema.ResourceImporter{StateContext: resourceTemplateImport}, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "name to give the template", - Required: true, - }, - "description": { - Type: schema.TypeString, - Description: "description for the template", - Optional: true, - }, - "repository": { - Type: schema.TypeString, - Description: "git repository url for the template source code", - Required: true, - }, - "path": { - Type: schema.TypeString, - Description: "terraform / terragrunt file folder inside source code", - Optional: true, - }, - "revision": { - Type: schema.TypeString, - Description: "source code revision (branch / tag) to use", - Optional: true, - }, - "type": { - Type: schema.TypeString, - Description: "'terraform' or 'terragrunt'", - Optional: true, - Default: "terraform", - }, - "ssh_keys": { - Type: schema.TypeList, - Description: "an array of references to 'data_ssh_key' to use when accessing git over ssh", - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeMap, - Description: "a map of env0_ssh_key.id and env0_ssh_key.name for each project", - }, - }, - "retries_on_deploy": { - Type: schema.TypeInt, - Description: "number of times to retry when deploying an environment based on this template", - Optional: true, - ValidateDiagFunc: validateRetries, - }, - "retry_on_deploy_only_when_matches_regex": { - Type: schema.TypeString, - Description: "if specified, will only retry (on deploy) if error matches specified regex", - Optional: true, - RequiredWith: []string{"retries_on_deploy"}, - }, - "retries_on_destroy": { - Type: schema.TypeInt, - Description: "number of times to retry when destroying an environment based on this template", - Optional: true, - ValidateDiagFunc: validateRetries, - }, - "retry_on_destroy_only_when_matches_regex": { - Type: schema.TypeString, - Description: "if specified, will only retry (on destroy) if error matches specified regex", - Optional: true, - RequiredWith: []string{"retries_on_destroy"}, - }, - "github_installation_id": { - Type: schema.TypeInt, - Description: "the env0 application installation id on the relevant github repository", - Optional: true, - ConflictsWith: allVCSAttributesBut("github_installation_id"), - }, - "token_id": { - Type: schema.TypeString, - Description: "the token id used for private git repos or for integration with GitLab, you can get this value by using a data resource of an existing Gitlab template or contact our support team", - Optional: true, - ConflictsWith: allVCSAttributesBut("token_id", "gitlab_project_id"), - }, - "gitlab_project_id": { - Type: schema.TypeInt, - Description: "the project id of the relevant repository", - Optional: true, - ConflictsWith: allVCSAttributesBut("token_id", "gitlab_project_id"), - RequiredWith: []string{"token_id"}, - }, - "terraform_version": { - Type: schema.TypeString, - Description: "the Terraform version to use (example: 0.15.1). Setting to `RESOLVE_FROM_TERRAFORM_CODE` defaults to the version of `terraform.required_version` during run-time (resolve from terraform code).", - Optional: true, - ValidateDiagFunc: NewRegexValidator(`^(?:[0-9]\.[0-9]{1,2}\.[0-9]{1,2})|RESOLVE_FROM_TERRAFORM_CODE$`), - Default: "0.15.1", - }, - "terragrunt_version": { - Type: schema.TypeString, - Description: "the Terragrunt version to use (example: 0.36.5)", - ValidateDiagFunc: NewRegexValidator(`^[0-9]\.[0-9]{1,2}\.[0-9]{1,2}$`), - Optional: true, - }, - "is_gitlab_enterprise": { - Type: schema.TypeBool, - Description: "true if this template uses gitlab enterprise repository", - Optional: true, - Default: "false", - ConflictsWith: allVCSAttributesBut("is_gitlab_enterprise"), - }, - "bitbucket_client_key": { - Type: schema.TypeString, - Description: "the bitbucket client key used for integration", - Optional: true, - ConflictsWith: allVCSAttributesBut("bitbucket_client_key"), - }, - "is_bitbucket_server": { - Type: schema.TypeBool, - Description: "true if this template uses bitbucket server repository", - Optional: true, - Default: "false", - ConflictsWith: allVCSAttributesBut("is_bitbucket_server"), - }, - "is_github_enterprise": { - Type: schema.TypeBool, - Description: "true if this template uses github enterprise repository", - Optional: true, - Default: "false", - ConflictsWith: allVCSAttributesBut("is_github_enterprise"), - }, - }, + Schema: getTemplateSchema(TemplateTypeShared), } } diff --git a/env0/resource_template_test.go b/env0/resource_template_test.go index fa76cc9e..e996bd81 100644 --- a/env0/resource_template_test.go +++ b/env0/resource_template_test.go @@ -624,7 +624,7 @@ func TestUnitTemplateResource(t *testing.T) { Steps: []resource.TestStep{ { Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{"name": "test", "repository": "env0/test", attribute: amount}), - ExpectError: regexp.MustCompile("Retries amount must be between 1 and 3"), + ExpectError: regexp.MustCompile("retries amount must be between 1 and 3"), }, }, }) diff --git a/env0/templates.go b/env0/templates.go new file mode 100644 index 00000000..e6470f70 --- /dev/null +++ b/env0/templates.go @@ -0,0 +1,188 @@ +package env0 + +import ( + "sort" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type TemplateType int + +const ( + TemplateTypeSingle = 1 + TemplateTypeShared = 2 +) + +func getTemplateSchema(templateType TemplateType) map[string]*schema.Schema { + /* + * VCS Constraints: + * GitHub - githubInstallationId + * GitLab - gitlabProjectId and tokenId + * Bitbucket - bitbucketClientKey + * GH Enterprise - isGitHubEnterprise + * GL Enterprise - isGitLabEnterprise + * BB Server - isBitbucketServer + * Other - tokenId (optional field) + */ + + allVCSAttributes := []string{ + "token_id", + "gitlab_project_id", + "github_installation_id", + "bitbucket_client_key", + "is_gitlab_enterprise", + "is_bitbucket_server", + "is_github_enterprise", + } + + allVCSAttributesBut := func(strs ...string) []string { + sort.Strings(strs) + ret := []string{} + + for _, attr := range allVCSAttributes { + if sort.SearchStrings(strs, attr) >= len(strs) { + ret = append(ret, attr) + } + } + + return ret + } + + s := map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "name to give the template", + Required: templateType == TemplateTypeShared, + Computed: templateType == TemplateTypeSingle, + }, + "description": { + Type: schema.TypeString, + Description: "description for the template", + Optional: true, + Computed: templateType == TemplateTypeSingle, + }, + "repository": { + Type: schema.TypeString, + Description: "git repository url for the template source code", + Required: true, + }, + "path": { + Type: schema.TypeString, + Description: "terraform / terragrunt file folder inside source code", + Optional: true, + }, + "revision": { + Type: schema.TypeString, + Description: "source code revision (branch / tag) to use", + Optional: true, + }, + "type": { + Type: schema.TypeString, + Description: "'terraform' or 'terragrunt'", + Optional: true, + Default: "terraform", + }, + "ssh_keys": { + Type: schema.TypeList, + Description: "an array of references to 'data_ssh_key' to use when accessing git over ssh", + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeMap, + Description: "a map of env0_ssh_key.id and env0_ssh_key.name for each project", + }, + }, + "retries_on_deploy": { + Type: schema.TypeInt, + Description: "number of times to retry when deploying an environment based on this template", + Optional: true, + ValidateDiagFunc: ValidateRetries, + }, + "retry_on_deploy_only_when_matches_regex": { + Type: schema.TypeString, + Description: "if specified, will only retry (on deploy) if error matches specified regex", + Optional: true, + RequiredWith: []string{"retries_on_deploy"}, + }, + "retries_on_destroy": { + Type: schema.TypeInt, + Description: "number of times to retry when destroying an environment based on this template", + Optional: true, + ValidateDiagFunc: ValidateRetries, + }, + "retry_on_destroy_only_when_matches_regex": { + Type: schema.TypeString, + Description: "if specified, will only retry (on destroy) if error matches specified regex", + Optional: true, + RequiredWith: []string{"retries_on_destroy"}, + }, + "github_installation_id": { + Type: schema.TypeInt, + Description: "the env0 application installation id on the relevant github repository", + Optional: true, + ConflictsWith: allVCSAttributesBut("github_installation_id"), + }, + "token_id": { + Type: schema.TypeString, + Description: "the token id used for private git repos or for integration with GitLab, you can get this value by using a data resource of an existing Gitlab template or contact our support team", + Optional: true, + ConflictsWith: allVCSAttributesBut("token_id", "gitlab_project_id"), + }, + "gitlab_project_id": { + Type: schema.TypeInt, + Description: "the project id of the relevant repository", + Optional: true, + ConflictsWith: allVCSAttributesBut("token_id", "gitlab_project_id"), + RequiredWith: []string{"token_id"}, + }, + "terraform_version": { + Type: schema.TypeString, + Description: "the Terraform version to use (example: 0.15.1). Setting to `RESOLVE_FROM_TERRAFORM_CODE` defaults to the version of `terraform.required_version` during run-time (resolve from terraform code).", + Optional: true, + ValidateDiagFunc: NewRegexValidator(`^(?:[0-9]\.[0-9]{1,2}\.[0-9]{1,2})|RESOLVE_FROM_TERRAFORM_CODE$`), + Default: "0.15.1", + }, + "terragrunt_version": { + Type: schema.TypeString, + Description: "the Terragrunt version to use (example: 0.36.5)", + ValidateDiagFunc: NewRegexValidator(`^[0-9]\.[0-9]{1,2}\.[0-9]{1,2}$`), + Optional: true, + }, + "is_gitlab_enterprise": { + Type: schema.TypeBool, + Description: "true if this template uses gitlab enterprise repository", + Optional: true, + Default: "false", + ConflictsWith: allVCSAttributesBut("is_gitlab_enterprise"), + }, + "bitbucket_client_key": { + Type: schema.TypeString, + Description: "the bitbucket client key used for integration", + Optional: true, + ConflictsWith: allVCSAttributesBut("bitbucket_client_key"), + }, + "is_bitbucket_server": { + Type: schema.TypeBool, + Description: "true if this template uses bitbucket server repository", + Optional: true, + Default: "false", + ConflictsWith: allVCSAttributesBut("is_bitbucket_server"), + }, + "is_github_enterprise": { + Type: schema.TypeBool, + Description: "true if this template uses github enterprise repository", + Optional: true, + Default: "false", + ConflictsWith: allVCSAttributesBut("is_github_enterprise"), + }, + } + + if templateType == TemplateTypeSingle { + s["id"] = &schema.Schema{ + Type: schema.TypeString, + Description: "id of the template", + Computed: true, + } + } + + return s +} diff --git a/env0/validators.go b/env0/validators.go index f798be1f..7da94942 100644 --- a/env0/validators.go +++ b/env0/validators.go @@ -46,6 +46,15 @@ func ValidateNotEmptyString(i interface{}, path cty.Path) diag.Diagnostics { return nil } +func ValidateRetries(i interface{}, path cty.Path) diag.Diagnostics { + retries := i.(int) + if retries < 1 || retries > 3 { + return diag.Errorf("retries amount must be between 1 and 3") + } + + return nil +} + func NewRegexValidator(r string) schema.SchemaValidateDiagFunc { cr := regexp.MustCompile(r)