Skip to content

Commit

Permalink
feat: add basic implementation of tag_definitions data source
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesRudolph committed Nov 4, 2024
1 parent 49fc533 commit 2a22ed8
Show file tree
Hide file tree
Showing 8 changed files with 507 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
## 0.1.0 (Unreleased)
## 0.6.0 (Unreleased)

FEATURES:
- Added `meshstack_tag_definitions` data source
2 changes: 2 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type endpoints struct {
ProjectUserBindings *url.URL `json:"meshprojectuserbindings"`
ProjectGroupBindings *url.URL `json:"meshprojectgroupbindings"`
Tenants *url.URL `json:"meshtenants"`
TagDefinitions *url.URL `json:"meshtagdefinitions"`
}

type loginResponse struct {
Expand All @@ -63,6 +64,7 @@ func NewClient(rootUrl *url.URL, apiKey string, apiSecret string) (*MeshStackPro
ProjectUserBindings: rootUrl.JoinPath(apiMeshObjectsRoot, "meshprojectbindings", "userbindings"),
ProjectGroupBindings: rootUrl.JoinPath(apiMeshObjectsRoot, "meshprojectbindings", "groupbindings"),
Tenants: rootUrl.JoinPath(apiMeshObjectsRoot, "meshtenants"),
TagDefinitions: rootUrl.JoinPath(apiMeshObjectsRoot, "meshtagdefinitions"),
}

return client, nil
Expand Down
165 changes: 165 additions & 0 deletions client/tag_definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package client

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)

const CONTENT_TYPE_TAG_DEFINITION = "application/vnd.meshcloud.api.meshtagdefinition.v1.hal+json"

type MeshTagDefinition struct {
ApiVersion string `json:"apiVersion" tfsdk:"api_version"`
Kind string `json:"kind" tfsdk:"kind"`
Metadata MeshTagDefinitionMetadata `json:"metadata" tfsdk:"metadata"`
Spec MeshTagDefinitionSpec `json:"spec" tfsdk:"spec"`
}

type MeshTagDefinitionMetadata struct {
Name string `json:"name" tfsdk:"name"`
}

type MeshTagDefinitionSpec struct {
TargetKind string `json:"targetKind" tfsdk:"target_kind"`
Key string `json:"key" tfsdk:"key"`
ValueType MeshTagDefinitionValueType `json:"valueType" tfsdk:"value_type"`
Description string `json:"description" tfsdk:"description"`
DisplayName string `json:"displayName" tfsdk:"display_name"`
SortOrder int64 `json:"sortOrder" tfsdk:"sort_order"`
Mandatory bool `json:"mandatory" tfsdk:"mandatory"`
Immutable bool `json:"immutable" tfsdk:"immutable"`
Restricted bool `json:"restricted" tfsdk:"restricted"`
}

type MeshTagDefinitionValueType struct {
String *TagValueString `json:"string,omitempty" tfsdk:"string"`
Email *TagValueEmail `json:"email,omitempty" tfsdk:"email"`
Integer *TagValueInteger `json:"integer,omitempty" tfsdk:"integer"`
Number *TagValueNumber `json:"number,omitempty" tfsdk:"number"`
SingleSelect *TagValueSingleSelect `json:"singleSelect,omitempty" tfsdk:"single_select"`
MultiSelect *TagValueMultiSelect `json:"multiSelect,omitempty" tfsdk:"multi_select"`
}

type TagValueString struct {
DefaultValue string `json:"defaultValue,omitempty" tfsdk:"default_value"`
ValidationRegex string `json:"validationRegex,omitempty" tfsdk:"validation_regex"`
}

type TagValueEmail struct {
DefaultValue string `json:"defaultValue,omitempty" tfsdk:"default_value"`
ValidationRegex string `json:"validationRegex,omitempty" tfsdk:"validation_regex"`
}

type TagValueInteger struct {
DefaultValue int64 `json:"defaultValue,omitempty" tfsdk:"default_value"`
}

type TagValueNumber struct {
DefaultValue float64 `json:"defaultValue,omitempty" tfsdk:"default_value"`
}

type TagValueSingleSelect struct {
Options []string `json:"options,omitempty" tfsdk:"options"`
DefaultValue string `json:"defaultValue,omitempty" tfsdk:"default_value"`
}

type TagValueMultiSelect struct {
Options []string `json:"options,omitempty" tfsdk:"options"`
DefaultValue []string `json:"defaultValue,omitempty" tfsdk:"default_value"`
}

func (c *MeshStackProviderClient) urlForTagDefinition(name string) *url.URL {
return c.endpoints.TagDefinitions.JoinPath(name)
}

func (c *MeshStackProviderClient) ReadTagDefinitions() (*[]MeshTagDefinition, error) {
var all []MeshTagDefinition

pageNumber := 0
targetUrl := c.endpoints.TagDefinitions
query := targetUrl.Query()

for {
query.Set("page", fmt.Sprintf("%d", pageNumber))

targetUrl.RawQuery = query.Encode()

req, err := http.NewRequest("GET", targetUrl.String(), nil)
if err != nil {
return nil, err
}

req.Header.Set("Accept", CONTENT_TYPE_TAG_DEFINITION)

res, err := c.doAuthenticatedRequest(req)
if err != nil {
return nil, err
}

defer res.Body.Close()

data, err := io.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}

if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data)
}

var response struct {
Embedded struct {
MeshTagDefinitions []MeshTagDefinition `json:"meshTagDefinitions"`
} `json:"_embedded"`
Page struct {
Size int `json:"size"`
TotalElements int `json:"totalElements"`
TotalPages int `json:"totalPages"`
Number int `json:"number"`
} `json:"page"`
}

err = json.Unmarshal(data, &response)
if err != nil {
return nil, err
}

all = append(all, response.Embedded.MeshTagDefinitions...)

// Check if there are more pages
if response.Page.Number >= response.Page.TotalPages-1 {
break
}

pageNumber++
}

return &all, nil
}

func (c *MeshStackProviderClient) ReadTagDefinition(name string) (*MeshTagDefinition, error) {
targetUrl := c.urlForTagDefinition(name)
req, err := http.NewRequest("GET", targetUrl.String(), nil)
if err != nil {
return nil, err
}

resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to read tag definition: %s", resp.Status)
}

var tagDefinition MeshTagDefinition
if err := json.NewDecoder(resp.Body).Decode(&tagDefinition); err != nil {
return nil, err
}

return &tagDefinition, nil
}
116 changes: 116 additions & 0 deletions docs/data-sources/tag_definitions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "meshstack_tag_definitions Data Source - terraform-provider-meshstack"
subcategory: ""
description: |-
Tag definitions for the entire organization.
---

# meshstack_tag_definitions (Data Source)

Tag definitions for the entire organization.



<!-- schema generated by tfplugindocs -->
## Schema

### Read-Only

- `tag_definitions` (Attributes List) List of tag definitions (see [below for nested schema](#nestedatt--tag_definitions))

<a id="nestedatt--tag_definitions"></a>
### Nested Schema for `tag_definitions`

Read-Only:

- `api_version` (String) API Version of meshTagDefinition datatype. Matches the version part provided within the Accept request header.
- `kind` (String) As a common meshObject structure exists, every meshObject has a kind. This is always meshTagDefinition for this endpoint.
- `metadata` (Attributes) Always contains the 'name' to uniquely identify the meshTagDefinition. (see [below for nested schema](#nestedatt--tag_definitions--metadata))
- `spec` (Attributes) Specification for the meshTagDefinition. (see [below for nested schema](#nestedatt--tag_definitions--spec))

<a id="nestedatt--tag_definitions--metadata"></a>
### Nested Schema for `tag_definitions.metadata`

Read-Only:

- `name` (String) Must be of the form $targetKind.$key since tag definitions must be non-conflicting.


<a id="nestedatt--tag_definitions--spec"></a>
### Nested Schema for `tag_definitions.spec`

Read-Only:

- `description` (String) The detailed description of the tag.
- `display_name` (String) The display name of the tag.
- `immutable` (Boolean) Indicates whether the tag value is not editable after initially set.
- `key` (String) The key of the tag.
- `mandatory` (Boolean) Indicates whether the tag is mandatory.
- `restricted` (Boolean) Indicates whether only admins can edit this tag.
- `sort_order` (Number) The sort order for this tag when displayed in the UI. meshPanel sorts tags in ascending order.
- `target_kind` (String) The kind of meshObject this tag is defined for. Must be one of: meshProject, meshWorkspace, meshLandingZone, meshPaymentMethod or meshBuildingBlockDefinition.
- `value_type` (Attributes) The TagValueType of the tag. Must define exactly one of the available types. (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type))

<a id="nestedatt--tag_definitions--spec--value_type"></a>
### Nested Schema for `tag_definitions.spec.value_type`

Read-Only:

- `email` (Attributes) email address, represented as JSON string (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type--email))
- `integer` (Attributes) an integer, represented as a JSON number (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type--integer))
- `multi_select` (Attributes) one or multiple strings from a list of options, represented as a JSON array (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type--multi_select))
- `number` (Attributes) a decimal number, represented as a JSON number (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type--number))
- `single_select` (Attributes) a string from a list of options, represented as a JSON string (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type--single_select))
- `string` (Attributes) string, represented as JSON string (see [below for nested schema](#nestedatt--tag_definitions--spec--value_type--string))

<a id="nestedatt--tag_definitions--spec--value_type--email"></a>
### Nested Schema for `tag_definitions.spec.value_type.string`

Read-Only:

- `default_value` (String) The default value of the tag.
- `validation_regex` (String) The regex pattern that the tag value must match.


<a id="nestedatt--tag_definitions--spec--value_type--integer"></a>
### Nested Schema for `tag_definitions.spec.value_type.string`

Read-Only:

- `default_value` (Number) The default value of the tag.


<a id="nestedatt--tag_definitions--spec--value_type--multi_select"></a>
### Nested Schema for `tag_definitions.spec.value_type.string`

Read-Only:

- `default_value` (List of String) The default value of the tag.
- `options` (List of String) The allowed options for the tag as a string[]


<a id="nestedatt--tag_definitions--spec--value_type--number"></a>
### Nested Schema for `tag_definitions.spec.value_type.string`

Read-Only:

- `default_value` (Number) The default value of the tag.


<a id="nestedatt--tag_definitions--spec--value_type--single_select"></a>
### Nested Schema for `tag_definitions.spec.value_type.string`

Read-Only:

- `default_value` (String) The default value of the tag.
- `options` (List of String) The allowed options for the tag as a string[]


<a id="nestedatt--tag_definitions--spec--value_type--string"></a>
### Nested Schema for `tag_definitions.spec.value_type.string`

Read-Only:

- `default_value` (String) The default value of the tag.
- `validation_regex` (String) The regex pattern that the tag value must match.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "meshstack_tag_definitions" "all" {
# no attributes for filtering are supported at the moment
}
7 changes: 7 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
# https://github.com/golangci/golangci-lint
golangci-lint
];

# make tfplugindocs available in the shell, see https://github.com/hashicorp/terraform-plugin-docs?tab=readme-ov-file#installation
shellHook = ''
export GOBIN=$PWD/bin
export PATH=$GOBIN:$PATH
go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
'';
};
});
};
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (p *MeshStackProvider) DataSources(ctx context.Context) []func() datasource
NewProjectUserBindingDataSource,
NewProjectGroupBindingDataSource,
NewTenantDataSource,
NewTagDefinitionsDataSource,
}
}

Expand Down
Loading

0 comments on commit 2a22ed8

Please sign in to comment.