From a4a7b302d940ea2653836d84a16fae3a4bc033de Mon Sep 17 00:00:00 2001 From: Yonatan Koren <10080107+korenyoni@users.noreply.github.com> Date: Sun, 12 Mar 2023 03:08:11 +0200 Subject: [PATCH 1/4] WIP --- client/pipeline.go | 28 +++++++ codefresh/data_pipelines.go | 150 ++++++++++++++++++++++++++++++++++++ codefresh/data_users.go | 3 + codefresh/provider.go | 1 + 4 files changed, 182 insertions(+) create mode 100644 codefresh/data_pipelines.go diff --git a/client/pipeline.go b/client/pipeline.go index f1d4465..0d50558 100644 --- a/client/pipeline.go +++ b/client/pipeline.go @@ -6,6 +6,11 @@ import ( "strings" ) +type Pipelines struct { + Docs []Pipeline `json:"docs,omitempty"` + Count int `json:"count,omitempty"` +} + type ErrorResponse struct { Status int `json:"status,omitempty"` Message string `json:"message,omitempty"` @@ -179,6 +184,29 @@ func (client *Client) GetPipeline(name string) (*Pipeline, error) { return &pipeline, nil } +func (client *Client) GetPipelines() (*[]Pipeline, error) { + fullPath := "/pipelines" + opts := RequestOptions{ + Path: fullPath, + Method: "GET", + } + + resp, err := client.RequestAPI(&opts) + + if err != nil { + return nil, err + } + + var getPipelines Pipelines + + err = DecodeResponseInto(resp, &getPipelines) + if err != nil { + return nil, err + } + + return &getPipelines.Docs, nil +} + func (client *Client) CreatePipeline(pipeline *Pipeline) (*Pipeline, error) { body, err := EncodeToJSON(pipeline) diff --git a/codefresh/data_pipelines.go b/codefresh/data_pipelines.go new file mode 100644 index 0000000..7e56cc0 --- /dev/null +++ b/codefresh/data_pipelines.go @@ -0,0 +1,150 @@ +package codefresh + +import ( + "fmt" + "time" + + cfClient "github.com/codefresh-io/terraform-provider-codefresh/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourcePipelines() *schema.Resource { + return &schema.Resource{ + Description: "This resource retrives Pipeline based on the provided attributes. Currently `spec` is limited to the YAML spec.", + Read: dataSourcePipelinesRead, + Schema: map[string]*schema.Schema{ + "filter": { + Description: "The query to use when retrieving pipelines. See: [API Documentation](https://g.codefresh.io/api/#operation/pipelines-get-names).", + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Description: "The name of the attribute to filter by. Must be a valid path to a field in the pipeline object. Accepts regex expressions.", + Type: schema.TypeString, + Required: true, + }, + "values": { + Description: "The acceptable values of the filter.", + Type: schema.TypeList, + Required: true, + Elem: schema.TypeString, + }, + }, + }, + }, + "pipelines": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "project": { + Type: schema.TypeString, + Computed: true, + }, + "tags": { + Type: schema.TypeList, + Computed: true, + Elem: schema.TypeString, + }, + "is_public": { + Type: schema.TypeBool, + Computed: true, + }, + "spec": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourcePipelinesRead(d *schema.ResourceData, meta interface{}) error { + + client := meta.(*cfClient.Client) + + pipelines, err := client.GetPipelines() + if err != nil { + return err + } + + err = mapDataPipelinesToResource(*pipelines, d) + if err != nil { + return err + } + + d.SetId(time.Now().UTC().String()) + + return nil +} + +func mapDataPipelinesToResource(pipelines []cfClient.Pipeline, d *schema.ResourceData) error { + var res = make([]map[string]interface{}, len(pipelines)) + for i, p := range pipelines { + m := make(map[string]interface{}) + m["id"] = p.Metadata.ID + m["name"] = p.Metadata.Name + m["project"] = p.Metadata.Project + m["tags"] = p.Metadata.Labels.Tags + m["is_public"] = p.Metadata.IsPublic + m["spec"] = p.Metadata.OriginalYamlString + + res[i] = m + } + + filteredPipelines := make([]map[string]interface{}, 0) + for i, p := range res { + match := false + if d.Get(fmt.Sprintf("filter.%d", i)).(*schema.Set).Len() == 0 { + match = true + } + + //for _, f := range d.Get("filter").(*schema.Set).List() { + // name := f.(map[string]interface{})["name"].(string) + // values := f.(map[string]interface{})["values"].([]string) + + // attribute, ok := p[name] + // if !ok { + // return errors.New("Invalid filter name: " + name) + // } + + // for _, v := range values { + // r, err := regexp.Compile(v) + // if err != nil { + // return errors.New("Not a valid regular expression: " + v) + // } + + // switch attribute.(type) { + // case bool, string: + // match = match || r.MatchString(attribute.(string)) + // case []string: + // for _, s := range attribute.([]string) { + // match = match || r.MatchString(s) + // } + // } + // } + //} + + if match { + filteredPipelines = append(filteredPipelines, p) + } + } + + err := d.Set("pipelines", filteredPipelines) + if err != nil { + return err + } + + return nil +} diff --git a/codefresh/data_users.go b/codefresh/data_users.go index 5495d6b..43cd89d 100644 --- a/codefresh/data_users.go +++ b/codefresh/data_users.go @@ -33,6 +33,9 @@ func dataSourceUsersRead(d *schema.ResourceData, meta interface{}) error { } err = mapDataUsersToResource(*users, d) + if err != nil { + return err + } d.SetId(time.Now().UTC().String()) diff --git a/codefresh/provider.go b/codefresh/provider.go index 4e90198..fba2329 100644 --- a/codefresh/provider.go +++ b/codefresh/provider.go @@ -39,6 +39,7 @@ func Provider() *schema.Provider { "codefresh_user": dataSourceUser(), "codefresh_users": dataSourceUsers(), "codefresh_registry": dataSourceRegistry(), + "codefresh_pipelines": dataSourcePipelines(), }, ResourcesMap: map[string]*schema.Resource{ "codefresh_account": resourceAccount(), From fd31da2213b97f6427a9e471d06731182a57b239 Mon Sep 17 00:00:00 2001 From: Yonatan Koren <10080107+korenyoni@users.noreply.github.com> Date: Sun, 12 Mar 2023 03:21:31 +0200 Subject: [PATCH 2/4] Basic pipeline data source. --- codefresh/data_pipelines.go | 67 ++++++++++--------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/codefresh/data_pipelines.go b/codefresh/data_pipelines.go index 7e56cc0..fa57188 100644 --- a/codefresh/data_pipelines.go +++ b/codefresh/data_pipelines.go @@ -2,6 +2,7 @@ package codefresh import ( "fmt" + "regexp" "time" cfClient "github.com/codefresh-io/terraform-provider-codefresh/client" @@ -10,32 +11,18 @@ import ( func dataSourcePipelines() *schema.Resource { return &schema.Resource{ - Description: "This resource retrives Pipeline based on the provided attributes. Currently `spec` is limited to the YAML spec.", + Description: "This resource retrives Pipeline based on the provided attributes.", Read: dataSourcePipelinesRead, Schema: map[string]*schema.Schema{ - "filter": { - Description: "The query to use when retrieving pipelines. See: [API Documentation](https://g.codefresh.io/api/#operation/pipelines-get-names).", - Type: schema.TypeSet, + "name_regex": { + Description: "The name regular expression to filter pipelines by.", + Type: schema.TypeString, Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Description: "The name of the attribute to filter by. Must be a valid path to a field in the pipeline object. Accepts regex expressions.", - Type: schema.TypeString, - Required: true, - }, - "values": { - Description: "The acceptable values of the filter.", - Type: schema.TypeList, - Required: true, - Elem: schema.TypeString, - }, - }, - }, }, "pipelines": { - Type: schema.TypeList, - Computed: true, + Description: "The returned list of pipelines. Note that `spec` is currently limited to the YAML, because of the complexity of the object.", + Type: schema.TypeList, + Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { @@ -104,38 +91,20 @@ func mapDataPipelinesToResource(pipelines []cfClient.Pipeline, d *schema.Resourc } filteredPipelines := make([]map[string]interface{}, 0) - for i, p := range res { + for _, p := range res { match := false - if d.Get(fmt.Sprintf("filter.%d", i)).(*schema.Set).Len() == 0 { + + name, ok := d.GetOk("name_regex") + if !ok { match = true + } else { + r, err := regexp.Compile(name.(string)) + if err != nil { + return fmt.Errorf("`name_regex` is not a valid regular expression, %s", err.Error()) + } + match = r.MatchString(p["name"].(string)) } - //for _, f := range d.Get("filter").(*schema.Set).List() { - // name := f.(map[string]interface{})["name"].(string) - // values := f.(map[string]interface{})["values"].([]string) - - // attribute, ok := p[name] - // if !ok { - // return errors.New("Invalid filter name: " + name) - // } - - // for _, v := range values { - // r, err := regexp.Compile(v) - // if err != nil { - // return errors.New("Not a valid regular expression: " + v) - // } - - // switch attribute.(type) { - // case bool, string: - // match = match || r.MatchString(attribute.(string)) - // case []string: - // for _, s := range attribute.([]string) { - // match = match || r.MatchString(s) - // } - // } - // } - //} - if match { filteredPipelines = append(filteredPipelines, p) } From 9b29b8fcd8d5d353ede9e821dd0902071b806ecf Mon Sep 17 00:00:00 2001 From: Yonatan Koren <10080107+korenyoni@users.noreply.github.com> Date: Sun, 12 Mar 2023 03:21:54 +0200 Subject: [PATCH 3/4] Update docs. --- docs/data-sources/pipelines.md | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 docs/data-sources/pipelines.md diff --git a/docs/data-sources/pipelines.md b/docs/data-sources/pipelines.md new file mode 100644 index 0000000..52b7ff4 --- /dev/null +++ b/docs/data-sources/pipelines.md @@ -0,0 +1,39 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "codefresh_pipelines Data Source - terraform-provider-codefresh" +subcategory: "" +description: |- + This resource retrives Pipeline based on the provided attributes. +--- + +# codefresh_pipelines (Data Source) + +This resource retrives Pipeline based on the provided attributes. + + + + +## Schema + +### Optional + +- `name_regex` (String) The name regular expression to filter pipelines by. + +### Read-Only + +- `id` (String) The ID of this resource. +- `pipelines` (List of Object) The returned list of pipelines. Note that `spec` is currently limited to the YAML, because of the complexity of the object. (see [below for nested schema](#nestedatt--pipelines)) + + +### Nested Schema for `pipelines` + +Read-Only: + +- `id` (String) +- `is_public` (Boolean) +- `name` (String) +- `project` (String) +- `spec` (String) +- `tags` (List of String) + + From 1ca026d0263660397ee14feddd4c0b807ee4472b Mon Sep 17 00:00:00 2001 From: Yonatan Koren <10080107+korenyoni@users.noreply.github.com> Date: Sun, 12 Mar 2023 03:24:15 +0200 Subject: [PATCH 4/4] Update description. --- codefresh/data_pipelines.go | 2 +- docs/data-sources/pipelines.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/codefresh/data_pipelines.go b/codefresh/data_pipelines.go index fa57188..681489a 100644 --- a/codefresh/data_pipelines.go +++ b/codefresh/data_pipelines.go @@ -11,7 +11,7 @@ import ( func dataSourcePipelines() *schema.Resource { return &schema.Resource{ - Description: "This resource retrives Pipeline based on the provided attributes.", + Description: "This resource retrives all pipelines belonging to the current user, which can be optionally filtered by the name.", Read: dataSourcePipelinesRead, Schema: map[string]*schema.Schema{ "name_regex": { diff --git a/docs/data-sources/pipelines.md b/docs/data-sources/pipelines.md index 52b7ff4..a60dadc 100644 --- a/docs/data-sources/pipelines.md +++ b/docs/data-sources/pipelines.md @@ -3,12 +3,12 @@ page_title: "codefresh_pipelines Data Source - terraform-provider-codefresh" subcategory: "" description: |- - This resource retrives Pipeline based on the provided attributes. + This resource retrives all pipelines belonging to the current user, which can be optionally filtered by the name. --- # codefresh_pipelines (Data Source) -This resource retrives Pipeline based on the provided attributes. +This resource retrives all pipelines belonging to the current user, which can be optionally filtered by the name.