From 0f89767e9fb1b458478c6cf4f63d9c02b91ceb73 Mon Sep 17 00:00:00 2001 From: yaroslav-codefresh Date: Tue, 19 Oct 2021 20:35:15 +0300 Subject: [PATCH 1/5] add basic crud for registries --- client/client.go | 3 +- client/registry.go | 125 +++++++++++++++++++ codefresh/provider.go | 1 + codefresh/resource_registry.go | 174 +++++++++++++++++++++++++++ examples/registries/main.tf | 28 +++++ examples/registries/terraform.tfvars | 3 + 6 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 client/registry.go create mode 100644 codefresh/resource_registry.go create mode 100644 examples/registries/main.tf create mode 100644 examples/registries/terraform.tfvars diff --git a/client/client.go b/client/client.go index df0f77c4..30abcb93 100644 --- a/client/client.go +++ b/client/client.go @@ -72,7 +72,8 @@ func (client *Client) RequestAPI(opt *RequestOptions) ([]byte, error) { return nil, fmt.Errorf("Failed to read body %v %v", resp.StatusCode, resp.Status) } - if resp.StatusCode != 200 { + // todo: maybe other 2**? + if resp.StatusCode != 200 && resp.StatusCode != 201 { return nil, fmt.Errorf("%v, %s", resp.Status, string(body)) } return body, nil diff --git a/client/registry.go b/client/registry.go new file mode 100644 index 00000000..4751556a --- /dev/null +++ b/client/registry.go @@ -0,0 +1,125 @@ +package client + +import ( + "fmt" + "log" + "net/url" +) + +type Registry struct { + Id string `json:"_id,omitempty"` + Name string `json:"name,omitempty"` + Kind string `json:"kind,omitempty"` + Provider string `json:"provider,omitempty"` + Domain string `json:"domain,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Default bool `json:"default,omitempty"` + Primary bool `json:"primary,omitempty"` + BehindFirewall bool `json:"behindFirewall,omitempty"` + DenyCompositeDomain bool `json:"denyCompositeDomain,omitempty"` +} + +func (registry *Registry) GetID() string { + return registry.Id +} + +func (client *Client) GetRegistry(name string) (*Registry, error) { + fullPath := fmt.Sprintf("/registries/%s", url.PathEscape(name)) + opts := RequestOptions{ + Path: fullPath, + Method: "GET", + } + + resp, err := client.RequestAPI(&opts) + + if err != nil { + return nil, err + } + var respRegistry Registry + err = DecodeResponseInto(resp, &respRegistry) + if err != nil { + return nil, err + } + + return &respRegistry, nil + +} + +func (client *Client) CreateRegistry(registry *Registry) (*Registry, error) { + + body, err := EncodeToJSON(registry) + + if err != nil { + return nil, err + } + opts := RequestOptions{ + Path: "/registries", + Method: "POST", + Body: body, + } + + resp, err := client.RequestAPI(&opts) + + if err != nil { + log.Printf("[DEBUG] Call to API for registry creation failed with Error = %v for Body %v", err, body) + return nil, err + } + + var respRegistry Registry + err = DecodeResponseInto(resp, &respRegistry) + if err != nil { + return nil, err + } + + return &respRegistry, nil + +} + +func (client *Client) UpdateRegistry(registry *Registry) (*Registry, error) { + + body, err := EncodeToJSON(registry) + + if err != nil { + return nil, err + } + + fullPath := fmt.Sprintf("/registries/%s", url.PathEscape(registry.Id)) + opts := RequestOptions{ + Path: fullPath, + Method: "PATCH", + Body: body, + } + + resp, err := client.RequestAPI(&opts) + + if err != nil { + return nil, err + } + + var respRegistry Registry + err = DecodeResponseInto(resp, &respRegistry) + if err != nil { + return nil, err + } + + return &respRegistry, nil + +} + +func (client *Client) DeleteRegistry(name string) error { + + fullPath := fmt.Sprintf("/registries/%s", url.PathEscape(name)) + opts := RequestOptions{ + Path: fullPath, + Method: "DELETE", + } + + _, err := client.RequestAPI(&opts) + + if err != nil { + return err + } + + return nil +} diff --git a/codefresh/provider.go b/codefresh/provider.go index bdf41828..63daf656 100644 --- a/codefresh/provider.go +++ b/codefresh/provider.go @@ -41,6 +41,7 @@ func Provider() *schema.Provider { "codefresh_account_admins": resourceAccountAdmins(), "codefresh_api_key": resourceApiKey(), "codefresh_context": resourceContext(), + "codefresh_registry": resourceRegistry(), "codefresh_idp_accounts": resourceIDPAccounts(), "codefresh_permission": resourcePermission(), "codefresh_pipeline": resourcePipeline(), diff --git a/codefresh/resource_registry.go b/codefresh/resource_registry.go new file mode 100644 index 00000000..349df040 --- /dev/null +++ b/codefresh/resource_registry.go @@ -0,0 +1,174 @@ +package codefresh + +import ( + "log" + + cfClient "github.com/codefresh-io/terraform-provider-codefresh/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// todo: 1) decide about password +// todo: 2) add another registry types +// todo: 3) add data definitions +// todo: 4) add more fields + +func resourceRegistry() *schema.Resource { + return &schema.Resource{ + Create: resourceRegistryCreate, + Read: resourceRegistryRead, + Update: resourceRegistryUpdate, + Delete: resourceRegistryDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "kind": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "registry_provider": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "domain": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "username": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "password": { + Type: schema.TypeString, + Optional: true, + ForceNew: false, + }, + "default": { + Type: schema.TypeBool, + Optional: true, + ForceNew: false, + }, + "primary": { + Type: schema.TypeBool, + Optional: true, + ForceNew: false, + }, + "behind_firewall": { + Type: schema.TypeBool, + Optional: true, + ForceNew: false, + }, + "deny_composite_domain": { + Type: schema.TypeBool, + Optional: true, + ForceNew: false, + }, + }, + } +} + +func resourceRegistryCreate(d *schema.ResourceData, meta interface{}) error { + + client := meta.(*cfClient.Client) + resp, err := client.CreateRegistry(mapResourceToRegistry(d)) + if err != nil { + log.Printf("[DEBUG] Error while creating registry. Error = %v", err) + return err + } + + d.SetId(resp.Id) + return resourceRegistryRead(d, meta) +} + +func resourceRegistryRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*cfClient.Client) + + registryId := d.Id() + + if registryId == "" { + d.SetId("") + return nil + } + + registry, err := client.GetRegistry(registryId) + if err != nil { + log.Printf("[DEBUG] Error while getting registry. Error = %v", err) + return err + } + + err = mapRegistryToResource(*registry, d) + if err != nil { + log.Printf("[DEBUG] Error while mapping registry to resource. Error = %v", err) + return err + } + + return nil +} + +func resourceRegistryUpdate(d *schema.ResourceData, meta interface{}) error { + + client := meta.(*cfClient.Client) + + registry := *mapResourceToRegistry(d) + registry.Id = d.Id() + + _, err := client.UpdateRegistry(®istry) + if err != nil { + log.Printf("[DEBUG] Error while updating registry. Error = %v", err) + return err + } + + return resourceRegistryRead(d, meta) +} + +func resourceRegistryDelete(d *schema.ResourceData, meta interface{}) error { + + client := meta.(*cfClient.Client) + + err := client.DeleteRegistry(d.Id()) + if err != nil { + return err + } + + return nil +} + +func mapResourceToRegistry(d *schema.ResourceData) *cfClient.Registry { + registry := &cfClient.Registry{ + Id: d.Id(), + Name: d.Get("name").(string), + Kind: d.Get("kind").(string), + Provider: d.Get("registry_provider").(string), + Domain: d.Get("domain").(string), + } + + if data, ok := d.GetOk("username"); ok { + registry.Username = data.(string) + } + if data, ok := d.GetOk("password"); ok { + registry.Password = data.(string) + } + + return registry +} + +func mapRegistryToResource(registry cfClient.Registry, d *schema.ResourceData) error { + d.SetId(registry.Id) + d.Set("name", registry.Name) + d.Set("kind", registry.Kind) + d.Set("registry_provider", registry.Provider) + d.Set("domain", registry.Domain) + d.Set("username", registry.Username) + d.Set("password", registry.Password) + + return nil +} diff --git a/examples/registries/main.tf b/examples/registries/main.tf new file mode 100644 index 00000000..86952afb --- /dev/null +++ b/examples/registries/main.tf @@ -0,0 +1,28 @@ + +variable api_url { + type = string +} + +variable token { + type = string + default = "" +} + +variable test_password { + type = string + default = "" +} + +provider "codefresh" { + api_url = var.api_url + token = var.token +} + +resource "codefresh_registry" "test" { + name = "test" + kind = "standard" + registry_provider = "other" + domain = "test1.io" + username = "test" + password = var.test_password +} \ No newline at end of file diff --git a/examples/registries/terraform.tfvars b/examples/registries/terraform.tfvars new file mode 100644 index 00000000..62a16f34 --- /dev/null +++ b/examples/registries/terraform.tfvars @@ -0,0 +1,3 @@ +api_url = "http://example.com/api" +token = "" + From 69bd27c5d6165bfd292d1e0a0dadcef194208415 Mon Sep 17 00:00:00 2001 From: yaroslav-codefresh Date: Thu, 21 Oct 2021 19:07:01 +0300 Subject: [PATCH 2/5] add registry types and mappings --- client/registry.go | 44 +++- codefresh/resource_registry.go | 421 +++++++++++++++++++++++++++++---- examples/registries/main.tf | 105 +++++++- 3 files changed, 498 insertions(+), 72 deletions(-) diff --git a/client/registry.go b/client/registry.go index 4751556a..6888957f 100644 --- a/client/registry.go +++ b/client/registry.go @@ -7,17 +7,37 @@ import ( ) type Registry struct { - Id string `json:"_id,omitempty"` - Name string `json:"name,omitempty"` - Kind string `json:"kind,omitempty"` - Provider string `json:"provider,omitempty"` - Domain string `json:"domain,omitempty"` - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Default bool `json:"default,omitempty"` - Primary bool `json:"primary,omitempty"` - BehindFirewall bool `json:"behindFirewall,omitempty"` - DenyCompositeDomain bool `json:"denyCompositeDomain,omitempty"` + // common + Id string `json:"_id,omitempty"` + Name string `json:"name,omitempty"` + Kind string `json:"kind,omitempty"` + Default bool `json:"default,omitempty"` + Primary bool `json:"primary,omitempty"` + BehindFirewall bool `json:"behindFirewall,omitempty"` + FallbackRegistry string `json:"fallbackRegistry,omitempty"` + RepositoryPrefix string `json:"repositoryPrefix,omitempty"` + Provider string `json:"provider,omitempty"` + + // mostly all + Domain string `json:"domain,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + + // bintray + Token string `json:"token,omitempty"` + + // ecr + AccessKeyId string `json:"accessKeyId,omitempty"` + SecretAccessKey string `json:"secretAccessKey,omitempty"` + Region string `json:"region,omitempty"` + + // gcr, gar + Keyfile string `json:"keyfile,omitempty"` + + // acr + ClientId string `json:"clientId,omitempty"` + ClientSecret string `json:"clientSecret,omitempty"` + //DenyCompositeDomain bool `json:"denyCompositeDomain,omitempty"` } func (registry *Registry) GetID() string { @@ -25,7 +45,7 @@ func (registry *Registry) GetID() string { } func (client *Client) GetRegistry(name string) (*Registry, error) { - fullPath := fmt.Sprintf("/registries/%s", url.PathEscape(name)) + fullPath := fmt.Sprintf("/registries/%s?includePrivate=true", url.PathEscape(name)) opts := RequestOptions{ Path: fullPath, Method: "GET", diff --git a/codefresh/resource_registry.go b/codefresh/resource_registry.go index 349df040..50a5e9a3 100644 --- a/codefresh/resource_registry.go +++ b/codefresh/resource_registry.go @@ -1,16 +1,35 @@ package codefresh import ( + "fmt" "log" cfClient "github.com/codefresh-io/terraform-provider-codefresh/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// todo: 1) decide about password -// todo: 2) add another registry types -// todo: 3) add data definitions -// todo: 4) add more fields +// todo: 1) add data definitions +// todo: 2) add tests + +const ( + providerOther = "other" + providerGcr = "gcr" + providerGar = "gar" + providerEcr = "ecr" + providerAcr = "acr" + providerDockerhub = "dockerhub" + providerBintray = "bintray" +) + +var providers = []string{ + providerOther, + providerGcr, + providerGar, + providerEcr, + providerAcr, + providerDockerhub, + providerBintray, +} func resourceRegistry() *schema.Resource { return &schema.Resource{ @@ -25,52 +44,225 @@ func resourceRegistry() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ForceNew: false, }, "kind": { Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "registry_provider": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "domain": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "username": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "password": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, + Computed: true, }, "default": { Type: schema.TypeBool, Optional: true, - ForceNew: false, + Default: false, }, "primary": { Type: schema.TypeBool, Optional: true, - ForceNew: false, + Default: true, }, - "behind_firewall": { - Type: schema.TypeBool, + "fallback_registry": { + Type: schema.TypeString, Optional: true, - ForceNew: false, + ForceNew: true, }, - "deny_composite_domain": { - Type: schema.TypeBool, - Optional: true, - ForceNew: false, + "spec": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + providerAcr: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 1, + ConflictsWith: getConflictingProviders(providers, providerAcr), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Required: true, + }, + "client_secret": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "domain": { + Type: schema.TypeString, + Required: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + providerGcr: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 1, + ConflictsWith: getConflictingProviders(providers, providerGcr), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "domain": { + Type: schema.TypeString, + Required: true, + }, + "keyfile": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + providerGar: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 1, + ConflictsWith: getConflictingProviders(providers, providerGar), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "domain": { + Type: schema.TypeString, + Required: true, + }, + "keyfile": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + providerEcr: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 1, + ConflictsWith: getConflictingProviders(providers, providerEcr), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "region": { + Type: schema.TypeString, + Required: true, + }, + "access_key_id": { + Type: schema.TypeString, + Required: true, + }, + "secret_access_key": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + providerBintray: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 1, + ConflictsWith: getConflictingProviders(providers, providerBintray), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Required: true, + }, + "token": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "domain": { + Type: schema.TypeString, + Required: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + providerDockerhub: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 1, + ConflictsWith: getConflictingProviders(providers, providerDockerhub), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Required: true, + }, + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + }, + }, + }, + providerOther: { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + ConflictsWith: getConflictingProviders(providers, providerOther), + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Required: true, + }, + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "domain": { + Type: schema.TypeString, + Required: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "behind_firewall": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + }, + }, }, }, } @@ -144,18 +336,80 @@ func resourceRegistryDelete(d *schema.ResourceData, meta interface{}) error { func mapResourceToRegistry(d *schema.ResourceData) *cfClient.Registry { registry := &cfClient.Registry{ - Id: d.Id(), - Name: d.Get("name").(string), - Kind: d.Get("kind").(string), - Provider: d.Get("registry_provider").(string), - Domain: d.Get("domain").(string), + Id: d.Id(), + Name: d.Get("name").(string), + Kind: d.Get("kind").(string), + Default: d.Get("default").(bool), + Primary: d.Get("primary").(bool), + FallbackRegistry: d.Get("fallback_registry").(string), + } + + var providerKey string + providerKey = "spec.0." + providerAcr + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerAcr + registry.Domain = d.Get(providerKey + ".0.domain").(string) + registry.ClientId = d.Get(providerKey + ".0.client_id").(string) + registry.ClientSecret = d.Get(providerKey + ".0.client_secret").(string) + registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) + return registry + } + + providerKey = "spec.0." + providerEcr + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerEcr + registry.Region = d.Get(providerKey + ".0.region").(string) + registry.AccessKeyId = d.Get(providerKey + ".0.access_key_id").(string) + registry.SecretAccessKey = d.Get(providerKey + ".0.secret_access_key").(string) + registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) + return registry + } + + providerKey = "spec.0." + providerGcr + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerGcr + registry.Domain = d.Get(providerKey + ".0.domain").(string) + registry.Keyfile = d.Get(providerKey + ".0.keyfile").(string) + registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) + return registry } - if data, ok := d.GetOk("username"); ok { - registry.Username = data.(string) + providerKey = "spec.0." + providerGar + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerGar + registry.Domain = d.Get(providerKey + ".0.domain").(string) + registry.Keyfile = d.Get(providerKey + ".0.keyfile").(string) + registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) + return registry } - if data, ok := d.GetOk("password"); ok { - registry.Password = data.(string) + + providerKey = "spec.0." + providerDockerhub + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerDockerhub + registry.Username = d.Get(providerKey + ".0.username").(string) + registry.Password = d.Get(providerKey + ".0.password").(string) + return registry + } + + providerKey = "spec.0." + providerBintray + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerBintray + registry.Domain = d.Get(providerKey + ".0.domain").(string) + registry.Username = d.Get(providerKey + ".0.username").(string) + registry.Token = d.Get(providerKey + ".0.token").(string) + registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) + return registry + } + + providerKey = "spec.0." + providerOther + if _, ok := d.GetOk(providerKey); ok { + registry.Provider = providerOther + registry.Domain = d.Get(providerKey + ".0.domain").(string) + registry.Username = d.Get(providerKey + ".0.username").(string) + registry.Password = d.Get(providerKey + ".0.password").(string) + registry.BehindFirewall = d.Get(providerKey + ".0.behind_firewall").(bool) + registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) + return registry } return registry @@ -165,10 +419,79 @@ func mapRegistryToResource(registry cfClient.Registry, d *schema.ResourceData) e d.SetId(registry.Id) d.Set("name", registry.Name) d.Set("kind", registry.Kind) - d.Set("registry_provider", registry.Provider) - d.Set("domain", registry.Domain) - d.Set("username", registry.Username) - d.Set("password", registry.Password) + d.Set("default", registry.Default) + d.Set("primary", registry.Primary) + d.Set("fallback_registry", registry.FallbackRegistry) + + if registry.Provider == providerAcr { + d.Set(fmt.Sprintf("spec.0.%v.0", providerAcr), map[string]interface{}{ + "domain": registry.Domain, + "client_id": registry.ClientId, + "client_secret": registry.ClientSecret, + "repository_prefix": registry.RepositoryPrefix, + }) + } + + if registry.Provider == providerEcr { + d.Set(fmt.Sprintf("spec.0.%v.0", providerEcr), map[string]interface{}{ + "region": registry.Domain, + "access_key_id": registry.AccessKeyId, + "secret_access_key": registry.SecretAccessKey, + "repository_prefix": registry.RepositoryPrefix, + }) + } + + if registry.Provider == providerGcr { + d.Set(fmt.Sprintf("spec.0.%v.0", providerGcr), map[string]interface{}{ + "domain": registry.Domain, + "keyfile": registry.Keyfile, + "repository_prefix": registry.RepositoryPrefix, + }) + } + + if registry.Provider == providerGar { + d.Set(fmt.Sprintf("spec.0.%v.0", providerGcr), map[string]interface{}{ + "domain": registry.Domain, + "keyfile": registry.Keyfile, + "repository_prefix": registry.RepositoryPrefix, + }) + } + + if registry.Provider == providerBintray { + d.Set(fmt.Sprintf("spec.0.%v.0", providerBintray), map[string]interface{}{ + "domain": registry.Domain, + "username": registry.Username, + "token": registry.Token, + "repository_prefix": registry.RepositoryPrefix, + }) + } + + if registry.Provider == providerDockerhub { + d.Set(fmt.Sprintf("spec.0.%v.0", providerDockerhub), map[string]interface{}{ + "username": registry.Username, + "password": registry.Password, + }) + } + + if registry.Provider == providerOther { + d.Set(fmt.Sprintf("spec.0.%v.0", providerOther), map[string]interface{}{ + "domain": registry.Domain, + "username": registry.Username, + "password": registry.Password, + "behind_firewall": registry.BehindFirewall, + "repository_prefix": registry.RepositoryPrefix, + }) + } return nil } + +func getConflictingProviders(arr []string, exclude string) []string { + filtered := make([]string, 0) + for _, provider := range arr { + if provider != exclude { + filtered = append(filtered, "spec.0."+provider) + } + } + return filtered +} diff --git a/examples/registries/main.tf b/examples/registries/main.tf index 86952afb..e7440d67 100644 --- a/examples/registries/main.tf +++ b/examples/registries/main.tf @@ -4,25 +4,108 @@ variable api_url { } variable token { - type = string + type = string default = "" } variable test_password { - type = string + type = string default = "" } provider "codefresh" { api_url = var.api_url - token = var.token + token = var.token } -resource "codefresh_registry" "test" { - name = "test" - kind = "standard" - registry_provider = "other" - domain = "test1.io" - username = "test" - password = var.test_password -} \ No newline at end of file +resource "codefresh_registry" "acr" { + name = "acr" + spec { + acr { + domain = "acr.io" + client_id = "test" + client_secret = "test" + repository_prefix = "test" + } + } +} + +resource "codefresh_registry" "gcr" { + name = "gcr" + spec { + gcr { + domain = "gcr.io" + keyfile = "test" + repository_prefix = "codefresh-inc" + } + } +} + +resource "codefresh_registry" "gar" { + name = "gar" + spec { + gar { + domain = "asia" + keyfile = "test" + repository_prefix = "codefresh-inc" + } + } +} + +resource "codefresh_registry" "dockerhub" { + name = "dockerhub1" + primary = false + spec { + dockerhub { + username = "test" + password = "test" + } + } +} + +resource "codefresh_registry" "bintray" { + name = "bintray" + spec { + bintray { + domain = "bintray.io" + username = "test" + token = "test" + } + } +} + +resource "codefresh_registry" "other" { + name = "other" + primary = true + spec { + other { + domain = "other.io" + username = "test" + password = "test" + } + } +} + +resource "codefresh_registry" "other1" { + name = "other1" + primary = false + spec { + other { + domain = "other.io" + username = "test" + password = "test" + } + } +} + +resource "codefresh_registry" "other2" { + name = "other2" + primary = false + spec { + other { + domain = "other.io" + username = "test" + password = "test" + } + } +} From 1dbdb2895a0b990d15167b5ff15e7a525d03346c Mon Sep 17 00:00:00 2001 From: yaroslav-codefresh Date: Mon, 25 Oct 2021 14:57:05 +0300 Subject: [PATCH 3/5] add registry data source --- client/registry.go | 5 +- codefresh/data_registry.go | 89 ++++++++++++++++++++++++++++++++++ codefresh/provider.go | 1 + codefresh/resource_registry.go | 1 + examples/registries/main.tf | 28 +++++++++-- 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 codefresh/data_registry.go diff --git a/client/registry.go b/client/registry.go index 6888957f..732b3c58 100644 --- a/client/registry.go +++ b/client/registry.go @@ -44,8 +44,9 @@ func (registry *Registry) GetID() string { return registry.Id } -func (client *Client) GetRegistry(name string) (*Registry, error) { - fullPath := fmt.Sprintf("/registries/%s?includePrivate=true", url.PathEscape(name)) +// GetRegistry identifier is ObjectId or name +func (client *Client) GetRegistry(identifier string) (*Registry, error) { + fullPath := fmt.Sprintf("/registries/%s", url.PathEscape(identifier)) opts := RequestOptions{ Path: fullPath, Method: "GET", diff --git a/codefresh/data_registry.go b/codefresh/data_registry.go new file mode 100644 index 00000000..0653f707 --- /dev/null +++ b/codefresh/data_registry.go @@ -0,0 +1,89 @@ +package codefresh + +import ( + "fmt" + + cfClient "github.com/codefresh-io/terraform-provider-codefresh/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceRegistry() *schema.Resource { + return &schema.Resource{ + Read: dataSourceRegistryRead, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "kind": { + Type: schema.TypeString, + Computed: true, + }, + "domain": { + Type: schema.TypeString, + Computed: true, + }, + "registry_provider": { + Type: schema.TypeString, + Computed: true, + }, + "default": { + Type: schema.TypeBool, + Computed: true, + }, + "primary": { + Type: schema.TypeBool, + Computed: true, + }, + "fallback_registry": { + Type: schema.TypeString, + Computed: true, + }, + "repository_prefix": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceRegistryRead(d *schema.ResourceData, meta interface{}) error { + + client := meta.(*cfClient.Client) + var registry *cfClient.Registry + var err error + + if name, nameOk := d.GetOk("name"); nameOk { + registry, err = client.GetRegistry(name.(string)) + } else { + return fmt.Errorf("data.codefresh_registry - must specify name") + } + if err != nil { + return err + } + + if registry == nil { + return fmt.Errorf("data.codefresh_registry - cannot find registry") + } + + return mapDataRegistryToResource(registry, d) +} + +func mapDataRegistryToResource(registry *cfClient.Registry, d *schema.ResourceData) error { + + if registry == nil || registry.Name == "" { + return fmt.Errorf("data.codefresh_registry - failed to mapDataRegistryToResource") + } + d.SetId(registry.Id) + + d.Set("name", registry.Name) + d.Set("registry_provider", registry.Provider) + d.Set("kind", registry.Kind) + d.Set("domain", registry.Domain) + d.Set("primary", registry.Primary) + d.Set("default", registry.Default) + d.Set("fallback_registry", registry.FallbackRegistry) + d.Set("repository_prefix", registry.RepositoryPrefix) + + return nil +} diff --git a/codefresh/provider.go b/codefresh/provider.go index 63daf656..4e2b8c0e 100644 --- a/codefresh/provider.go +++ b/codefresh/provider.go @@ -35,6 +35,7 @@ func Provider() *schema.Provider { "codefresh_team": dataSourceTeam(), "codefresh_user": dataSourceUser(), "codefresh_users": dataSourceUsers(), + "codefresh_registry": dataSourceRegistry(), }, ResourcesMap: map[string]*schema.Resource{ "codefresh_account": resourceAccount(), diff --git a/codefresh/resource_registry.go b/codefresh/resource_registry.go index 50a5e9a3..e991447e 100644 --- a/codefresh/resource_registry.go +++ b/codefresh/resource_registry.go @@ -256,6 +256,7 @@ func resourceRegistry() *schema.Resource { "behind_firewall": { Type: schema.TypeBool, Optional: true, + Default: false, ForceNew: true, }, }, diff --git a/examples/registries/main.tf b/examples/registries/main.tf index e7440d67..3d260915 100644 --- a/examples/registries/main.tf +++ b/examples/registries/main.tf @@ -20,6 +20,7 @@ provider "codefresh" { resource "codefresh_registry" "acr" { name = "acr" + default = true spec { acr { domain = "acr.io" @@ -32,6 +33,8 @@ resource "codefresh_registry" "acr" { resource "codefresh_registry" "gcr" { name = "gcr" + # all registries SHOULD be dependent on each other to be created/updated sequentially + depends_on = [codefresh_registry.acr] spec { gcr { domain = "gcr.io" @@ -43,6 +46,7 @@ resource "codefresh_registry" "gcr" { resource "codefresh_registry" "gar" { name = "gar" + depends_on = [codefresh_registry.gcr] spec { gar { domain = "asia" @@ -52,19 +56,27 @@ resource "codefresh_registry" "gar" { } } -resource "codefresh_registry" "dockerhub" { +data "codefresh_registry" "dockerhub" { + name = "dockerhub" +} + +# example with using data reference to existing registry, not managed by terraform +resource "codefresh_registry" "dockerhub1" { name = "dockerhub1" - primary = false + primary = !data.codefresh_registry.dockerhub.primary + depends_on = [codefresh_registry.gar] spec { dockerhub { username = "test" password = "test" } } + fallback_registry = data.codefresh_registry.dockerhub.id } resource "codefresh_registry" "bintray" { name = "bintray" + depends_on = [codefresh_registry.dockerhub1] spec { bintray { domain = "bintray.io" @@ -76,7 +88,8 @@ resource "codefresh_registry" "bintray" { resource "codefresh_registry" "other" { name = "other" - primary = true + depends_on = [codefresh_registry.bintray] + primary = false spec { other { domain = "other.io" @@ -86,9 +99,14 @@ resource "codefresh_registry" "other" { } } +# when you have multiple registries under the same domain +# they MUST be dependant on each other and `primary` +# MUST be specified at least and only for one registry +# as `true` resource "codefresh_registry" "other1" { name = "other1" - primary = false + primary = true + depends_on = [codefresh_registry.other] spec { other { domain = "other.io" @@ -101,6 +119,7 @@ resource "codefresh_registry" "other1" { resource "codefresh_registry" "other2" { name = "other2" primary = false + depends_on = [codefresh_registry.other1, codefresh_registry.bintray] spec { other { domain = "other.io" @@ -108,4 +127,5 @@ resource "codefresh_registry" "other2" { password = "test" } } + fallback_registry = codefresh_registry.bintray.id } From 82d79aa7d6c144c41e0b9d8c687312ecdcd98a34 Mon Sep 17 00:00:00 2001 From: yaroslav-codefresh Date: Mon, 25 Oct 2021 17:17:54 +0300 Subject: [PATCH 4/5] add registry docs --- codefresh/resource_registry.go | 6 +- docs/README.md | 25 ++++ docs/data/registry.md | 39 +++++ docs/resources/registry.md | 264 +++++++++++++++++++++++++++++++++ examples/registries/main.tf | 30 ++-- 5 files changed, 346 insertions(+), 18 deletions(-) create mode 100644 docs/data/registry.md create mode 100644 docs/resources/registry.md diff --git a/codefresh/resource_registry.go b/codefresh/resource_registry.go index e991447e..b816820a 100644 --- a/codefresh/resource_registry.go +++ b/codefresh/resource_registry.go @@ -132,7 +132,7 @@ func resourceRegistry() *schema.Resource { ConflictsWith: getConflictingProviders(providers, providerGar), Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "domain": { + "location": { Type: schema.TypeString, Required: true, }, @@ -378,7 +378,7 @@ func mapResourceToRegistry(d *schema.ResourceData) *cfClient.Registry { providerKey = "spec.0." + providerGar if _, ok := d.GetOk(providerKey); ok { registry.Provider = providerGar - registry.Domain = d.Get(providerKey + ".0.domain").(string) + registry.Domain = d.Get(providerKey + ".0.location").(string) registry.Keyfile = d.Get(providerKey + ".0.keyfile").(string) registry.RepositoryPrefix = d.Get(providerKey + ".0.repository_prefix").(string) return registry @@ -452,7 +452,7 @@ func mapRegistryToResource(registry cfClient.Registry, d *schema.ResourceData) e if registry.Provider == providerGar { d.Set(fmt.Sprintf("spec.0.%v.0", providerGcr), map[string]interface{}{ - "domain": registry.Domain, + "location": registry.Domain, "keyfile": registry.Keyfile, "repository_prefix": registry.RepositoryPrefix, }) diff --git a/docs/README.md b/docs/README.md index 488190bd..5de14232 100644 --- a/docs/README.md +++ b/docs/README.md @@ -28,3 +28,28 @@ The following arguments are supported: * Create teams using [teams module](modules/teams.md) * Create permissions - [see example](../examples/permissions) + +## Resources +* [account](resources/account.md) +* [account-admins](resources/account-admins.md) +* [api-key](resources/api-key.md) +* [context](resources/context.md) +* [idp-accounts](resources/idp-accounts.md) +* [permissions](resources/permissions.md) +* [pipeline](resources/pipeline.md) +* [project](resources/project.md) +* [registry](resources/registry.md) +* [step-types](resources/step-types.md) +* [team](resources/team.md) +* [user](resources/user.md) + + +## Data sources +* [account](data/account.md) +* [context](data/context.md) +* [idps](data/idps.md) +* [registry](data/registry.md) +* [step-types](data/step-types.md) +* [team](data/team.md) +* [user](data/user.md) + diff --git a/docs/data/registry.md b/docs/data/registry.md new file mode 100644 index 00000000..5782f436 --- /dev/null +++ b/docs/data/registry.md @@ -0,0 +1,39 @@ +# Data Source: codefresh_registry +This data source allows retrieving information on any existing registry + +## Example Usage + +```hcl +# some pre-existing registry +data "codefresh_registry" "dockerhub" { + name = "dockerhub" +} + +# example with using data reference to existing registry, not managed by terraform +# "dockerhub" registry will be used as fallback for "dockerhub1" +resource "codefresh_registry" "dockerhub1" { + name = "dockerhub1" + primary = !data.codefresh_registry.dockerhub.primary + + spec { + dockerhub { + username = "test" + password = "test" + } + } + fallback_registry = data.codefresh_registry.dockerhub.id +} +``` + +## Argument Reference + +* `name` - (Required) Name of the registry to be retrieved + +## Attributes Reference + +* `domain` - String. +* `registry_provider` - String identifying the type of registry. E.g. `dockerhub, ecr, acr` and others +* `default` - Bool. +* `primary` - Bool. +* `fallback_registry` - String representing the id of the fallback registry. +* `repository prefix` - String representing the optional prefix for registry. diff --git a/docs/resources/registry.md b/docs/resources/registry.md new file mode 100644 index 00000000..a003ed3d --- /dev/null +++ b/docs/resources/registry.md @@ -0,0 +1,264 @@ +# Registry Resource + +Registry is the configuration that Codefresh uses to push/pull docker images. +For more details see the [Codefresh Docker Registries](https://codefresh.io/docs/docs/integrations/docker-registries/) + + +## Concurrency Limitation + +Codefresh Registry API was not designed initially to handle concurrent modifications on `registry` entity. +Thus, you need to take one of the following approaches to avoid **errors** and **non-expected behavior**: + +1) run terraform write operations with `-parallelism=1` option +```shell +terraform apply -parallelism=1 +terraform destroy -parallelism=1 +``` + +2) make each registry resource `depend_on` each other - so the CRUD operations will be performed for each registry **sequentially** +```hcl +resource "codefresh_registry" "dockerhub" { + name = "dockerhub" + + spec { + dockerhub { + # some specific fields here + } + } +} + +# this registry will depend on the "dockerhub" registry +resource "codefresh_registry" "gcr" { + name = "gcr" + + depends_on = [codefresh_registry.dockerhub] + spec { + gcr { + # some specific fields here + } + } +} +``` + +## Supported Registry Providers + +Currently, Codefresh supports the following registry providers: +* dockerhub - [Docker Hub](https://codefresh.io/docs/docs/integrations/docker-registries/docker-hub/) +* acr - [Azure Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/azure-docker-registry) +* gcr - [Google Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/google-container-registry) +* gar - [Google Artifact Registry](https://codefresh.io/docs/docs/integrations/docker-registries/google-artifact-registry) +* ecr - [Amazon EC2 Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/amazon-ec2-container-registry) +* bintray - [Bintray / Artifactory](https://codefresh.io/docs/docs/integrations/docker-registries/bintray-io) +* other - any other provider including [Quay](https://codefresh.io/docs/docs/integrations/docker-registries/quay-io) and [Github Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/github-container-registry). See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/other-registries). + +### Resource Spec + +Each registry resource have some common fields and specific ones stored under the `spec`. Here is the template: + +```hcl +resource "codefresh_registry" "some_registry" { + name = "some_name" + default = false + primary = true + fallback_registry = codefresh_registry.some_other_registry.id + + spec { + { + # some specific fields here + } + } +} +``` + + +### Common fields + +* `name` - `(Required)` some unique name for registry +* `default` - `(Optional, Default = false)` see the [Default Registry](https://codefresh.io/docs/docs/integrations/docker-registries/#the-default-registry) +* `primary` - `(Optional, Default = true)` see the [Multiple Registries](https://codefresh.io/docs/docs/ci-cd-guides/working-with-docker-registries/#working-with-multiple-registries-with-the-same-domain) +* `fallback_registry` - `(Optional)` see the [Fallback Registry](https://codefresh.io/docs/docs/integrations/docker-registries/#fallback-registry) + + +### Default registry usage + +If you want to manage default registry by Codefresh terraform provider correctly, +you need to mark only one registry as `default = true` + +```hcl +resource "codefresh_registry" "dockerhub" { + name = "dockerhub" + + spec { + dockerhub { + # some specific fields here + } + } +} + +# this registry will be default +resource "codefresh_registry" "gcr" { + name = "gcr" + default = true + fallback_registry = codefresh_registry.some_other_registry.id + + spec { + gcr { + # some specific fields here + } + } +} +``` + +### Primary registry usage + +If you are using [Multiple Registries](https://codefresh.io/docs/docs/ci-cd-guides/working-with-docker-registries/#working-with-multiple-registries-with-the-same-domain) feature +you need to manually mark each registry of the same domain as non-primary and only one as primary + +```hcl +# this registry will be primary +resource "codefresh_registry" "dockerhub" { + name = "dockerhub" + primary = true + + spec { + dockerhub { + # some specific fields here + } + } +} + +resource "codefresh_registry" "dockerhub1" { + name = "dockerhub1" + primary = false + + spec { + dockerhub { + # some specific fields here + } + } +} + +resource "codefresh_registry" "dockerhub2" { + name = "dockerhub2" + primary = false + + spec { + dockerhub { + # some specific fields here + } + } +} +``` + +### Fallback registry usage + +If you want to use one of your registries as fallback you need to specify its id +for `fallback_registry` field of another registry + +```hcl +resource "codefresh_registry" "dockerhub" { + name = "dockerhub" + + spec { + dockerhub { + # some specific fields here + } + } +} + +resource "codefresh_registry" "gcr" { + name = "gcr" + + # here we take the id of "dockerhub" registry + fallback_registry = codefresh_registry.dockerhub.id + + spec { + gcr { + # some specific fields here + } + } +} +``` + +## Argument Reference + +- `name` - _(Required)_ some unique name for registry +- `default` - _(Optional, Default = false)_ default registry +- `primary` - _(Optional, Default = true)_ primary registry +- `fallback_registry` - _(Optional)_ fallback registry +- `spec` - _(Required)_ A `spec` block as documented below. + +--- + +`spec` supports the following (Note: only 1 of the below can be specified at any time): + +- dockerhub - _(Optional)_ A `dockerhub` block as documented below ([Docker Hub Registry](https://codefresh.io/docs/docs/integrations/docker-registries/docker-hub/)) +- acr - _(Optional)_ An `acr` block as documented below ([Azure Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/azure-docker-registry)) +- gcr - _(Optional)_ A `gcr` block as documented below ([Google Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/google-container-registry)) +- gar - _(Optional)_ A `gar` block as documented below ([Google Artifact Registry](https://codefresh.io/docs/docs/integrations/docker-registries/google-artifact-registry)) +- ecr - _(Optional)_ An `ecr` block as documented below ([Amazon EC2 Container Registry](https://codefresh.io/docs/docs/integrations/docker-registries/amazon-ec2-container-registry)) +- bintray - _(Optional)_ A `bintray` block as documented below ([Bintray / Artifactory](https://codefresh.io/docs/docs/integrations/docker-registries/bintray-io)) +- other - _(Optional)_ `other` provider block described below ([Other Providers](https://codefresh.io/docs/docs/integrations/docker-registries/other-registries)). + + +--- + +`dockerhub` supports the following: + +- `username` - _(Required)_ String. +- `password` - _(Required, Sensitive)_ String. + +--- + +`acr` supports the following: + +- `domain` - _(Required)_ String representing your acr registry domain. +- `client_id` - _(Required)_ String representing client id. +- `client_secret` - _(Required)_ String representing client secret. +- `repository_prefix` - _(Optional)_ String. See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/#using-an-optional-repository-prefix). + +--- + +`gcr` supports the following: + +- `domain` - _(Required)_ String representing one of the Google's gcr domains +- `keyfile` - _(Required)_ String representing service account json file contents +- `repository_prefix` - _(Optional)_ String. See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/#using-an-optional-repository-prefix). + +--- + +`gar` supports the following: + +- `location` - _(Required)_ String representing one of the Google's gar locations +- `keyfile` - _(Required)_ String representing service account json file contents +- `repository_prefix` - _(Optional)_ String. See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/#using-an-optional-repository-prefix). + +--- + +`ecr` supports the following: + +- `region` - _(Required)_ String representing one of the Amazon regions +- `access_key_id` - _(Required)_ String representing access key id +- `secret_access_key` - _(Required)_ String representing secret access key +- `repository_prefix` - _(Optional)_ String. See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/#using-an-optional-repository-prefix). + +--- + +`bintray` supports the following: + +- `domain` - _(Required)_ String representing the bintray domain +- `username` - _(Required)_ String representing the username +- `token` - _(Required)_ String representing token +- `repository_prefix` - _(Optional)_ String. See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/#using-an-optional-repository-prefix). + +--- + +`other` supports the following: + +- `domain` - _(Required)_ String representing the bintray domain +- `username` - _(Required)_ String representing the username +- `password` - _(Required)_ String representing token +- `repository_prefix` - _(Optional)_ String. See the [docs](https://codefresh.io/docs/docs/integrations/docker-registries/#using-an-optional-repository-prefix). +- `behind_firewall` - _(Optional, Default = false)_ Bool. See the [docs](https://codefresh.io/docs/docs/administration/behind-the-firewall/#accessing-an-internal-docker-registry). + +--- \ No newline at end of file diff --git a/examples/registries/main.tf b/examples/registries/main.tf index 3d260915..33300230 100644 --- a/examples/registries/main.tf +++ b/examples/registries/main.tf @@ -19,7 +19,7 @@ provider "codefresh" { } resource "codefresh_registry" "acr" { - name = "acr" + name = "acr" default = true spec { acr { @@ -32,7 +32,7 @@ resource "codefresh_registry" "acr" { } resource "codefresh_registry" "gcr" { - name = "gcr" + name = "gcr" # all registries SHOULD be dependent on each other to be created/updated sequentially depends_on = [codefresh_registry.acr] spec { @@ -45,11 +45,11 @@ resource "codefresh_registry" "gcr" { } resource "codefresh_registry" "gar" { - name = "gar" + name = "gar" depends_on = [codefresh_registry.gcr] spec { gar { - domain = "asia" + location = "asia" keyfile = "test" repository_prefix = "codefresh-inc" } @@ -62,9 +62,9 @@ data "codefresh_registry" "dockerhub" { # example with using data reference to existing registry, not managed by terraform resource "codefresh_registry" "dockerhub1" { - name = "dockerhub1" - primary = !data.codefresh_registry.dockerhub.primary - depends_on = [codefresh_registry.gar] + name = "dockerhub1" + primary = !data.codefresh_registry.dockerhub.primary + depends_on = [codefresh_registry.gar] spec { dockerhub { username = "test" @@ -75,7 +75,7 @@ resource "codefresh_registry" "dockerhub1" { } resource "codefresh_registry" "bintray" { - name = "bintray" + name = "bintray" depends_on = [codefresh_registry.dockerhub1] spec { bintray { @@ -87,9 +87,9 @@ resource "codefresh_registry" "bintray" { } resource "codefresh_registry" "other" { - name = "other" + name = "other" depends_on = [codefresh_registry.bintray] - primary = false + primary = false spec { other { domain = "other.io" @@ -104,8 +104,8 @@ resource "codefresh_registry" "other" { # MUST be specified at least and only for one registry # as `true` resource "codefresh_registry" "other1" { - name = "other1" - primary = true + name = "other1" + primary = true depends_on = [codefresh_registry.other] spec { other { @@ -117,9 +117,9 @@ resource "codefresh_registry" "other1" { } resource "codefresh_registry" "other2" { - name = "other2" - primary = false - depends_on = [codefresh_registry.other1, codefresh_registry.bintray] + name = "other2" + primary = false + depends_on = [codefresh_registry.other1, codefresh_registry.bintray] spec { other { domain = "other.io" From ea8431ae014423ca84d12e2d34e6ef73a4929b64 Mon Sep 17 00:00:00 2001 From: yaroslav-codefresh Date: Tue, 26 Oct 2021 14:08:50 +0300 Subject: [PATCH 5/5] remove comments --- codefresh/resource_registry.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/codefresh/resource_registry.go b/codefresh/resource_registry.go index b816820a..a869df56 100644 --- a/codefresh/resource_registry.go +++ b/codefresh/resource_registry.go @@ -8,9 +8,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// todo: 1) add data definitions -// todo: 2) add tests - const ( providerOther = "other" providerGcr = "gcr"