From aa08bdf7b118fc04a6dc2a1416c49a59cc76253b Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Sat, 13 May 2023 21:19:13 -0400 Subject: [PATCH] Added `ns_env` data source. --- CHANGELOG.md | 9 +++ internal/provider/data_env.go | 116 +++++++++++++++++++++++++++++++ internal/provider/plan_config.go | 6 +- internal/provider/provider.go | 1 + website/docs/d/env.markdown | 40 +++++++++++ 5 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 internal/provider/data_env.go create mode 100644 website/docs/d/env.markdown diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a405a..dc1ea2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ +## 0.6.19 (May 13, 2023) + +FEATURES: + +* Added `ns_env` data source to read information about an environment. + ## 0.6.18 (Feb 16, 2023) + +FEATURES: + * Added `ns_env_variables` which takes in all the environment variables and secrets, performing interpolation and returning the results. * Added `ns_secret_keys` which takes in all the environment variables and secret keys. * This is useful when you need to do a for_each over the set of secret keys; this keeps the result static. diff --git a/internal/provider/data_env.go b/internal/provider/data_env.go new file mode 100644 index 0000000..376b7d4 --- /dev/null +++ b/internal/provider/data_env.go @@ -0,0 +1,116 @@ +package provider + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-go/tftypes" + "gopkg.in/nullstone-io/go-api-client.v0" + "gopkg.in/nullstone-io/go-api-client.v0/types" +) + +type dataEnv struct { + p *provider +} + +func newDataEnv(p *provider) (*dataEnv, error) { + if p == nil { + return nil, fmt.Errorf("a provider is required") + } + return &dataEnv{p: p}, nil +} + +func (*dataEnv) Schema(ctx context.Context) *tfprotov5.Schema { + return &tfprotov5.Schema{ + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Description: "Data source to read the nullstone environment", + DescriptionKind: tfprotov5.StringKindMarkdown, + Attributes: []*tfprotov5.SchemaAttribute{ + deprecatedIDAttribute(), + { + Name: "stack_id", + Type: tftypes.Number, + Description: "The stack ID that owns this environment", + Required: true, + DescriptionKind: tfprotov5.StringKindMarkdown, + }, + { + Name: "env_id", + Type: tftypes.Number, + Description: "The environment ID", + Required: true, + DescriptionKind: tfprotov5.StringKindMarkdown, + }, + { + Name: "name", + Type: tftypes.String, + Description: "The name of environment.", + DescriptionKind: tfprotov5.StringKindMarkdown, + Computed: true, + }, + { + Name: "type", + Type: tftypes.String, + Description: "The type of environment. Possible values: PipelineEnv, PreviewEnv, PreviewsSharedEnv, GlobalEnv", + DescriptionKind: tfprotov5.StringKindMarkdown, + Computed: true, + }, + { + Name: "pipeline_order", + Type: tftypes.Number, + Description: "If a PipelineEnv, this is a number representing which order in the pipeline.", + DescriptionKind: tfprotov5.StringKindMarkdown, + Computed: true, + }, + }, + }, + } +} + +func (d *dataEnv) Validate(ctx context.Context, config map[string]tftypes.Value) ([]*tfprotov5.Diagnostic, error) { + return nil, nil +} + +func (d *dataEnv) Read(ctx context.Context, config map[string]tftypes.Value) (map[string]tftypes.Value, []*tfprotov5.Diagnostic, error) { + nsConfig := d.p.NsConfig + nsClient := api.Client{Config: nsConfig} + + diags := make([]*tfprotov5.Diagnostic, 0) + + stackId := extractInt64FromConfig(config, "stack_id") + envId := extractInt64FromConfig(config, "env_id") + + var envName string + var envType types.EnvironmentType + var pipelineOrder int + + env, err := nsClient.Environments().Get(stackId, envId) + if err != nil { + diags = append(diags, &tfprotov5.Diagnostic{ + Severity: tfprotov5.DiagnosticSeverityError, + Summary: "Unable to find nullstone environment.", + Detail: err.Error(), + }) + } else if env != nil { + envName = env.Name + envType = env.Type + if env.PipelineOrder != nil { + pipelineOrder = *env.PipelineOrder + } + } else { + diags = append(diags, &tfprotov5.Diagnostic{ + Severity: tfprotov5.DiagnosticSeverityError, + Summary: fmt.Sprintf("The environment %d in the stack %d does not exist in nullstone.", stackId, envId), + }) + } + + return map[string]tftypes.Value{ + "id": tftypes.NewValue(tftypes.String, fmt.Sprintf("%d", envId)), + "stack_id": tftypes.NewValue(tftypes.Number, &stackId), + "env_id": tftypes.NewValue(tftypes.Number, &envId), + "name": tftypes.NewValue(tftypes.String, envName), + "type": tftypes.NewValue(tftypes.String, envType), + "pipeline_order": tftypes.NewValue(tftypes.Number, pipelineOrder), + }, diags, nil +} diff --git a/internal/provider/plan_config.go b/internal/provider/plan_config.go index e2e5616..2cd5ff6 100644 --- a/internal/provider/plan_config.go +++ b/internal/provider/plan_config.go @@ -28,9 +28,9 @@ func (c PlanConfig) WorkspaceTarget() types.WorkspaceTarget { // LoadPlanConfig loads nullstone context for the current workspace // Originally, this was in a file named `.nullstone.json`, but moved to `.nullstone/active-workspace.yml` // As a result, this function will attempt the following: -// 1. Load `.nullstone/active-workspace.yml` -// 2. If not found, load `.nullstone.json` -// 3. Fall back to environment variables for each attribute +// 1. Load `.nullstone/active-workspace.yml` +// 2. If not found, load `.nullstone.json` +// 3. Fall back to environment variables for each attribute func LoadPlanConfig() (PlanConfig, error) { c := planConfigFromEnv() diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3d61c06..9a3a668 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -56,6 +56,7 @@ func newProviderServer(version string, fn func() (api.Config, *tfe.Config, PlanC s.MustRegisterDataSource("ns_app_env", newDataAppEnv) s.MustRegisterDataSource("ns_env_variables", newDataEnvVariables) s.MustRegisterDataSource("ns_secret_keys", newDataSecretKeys) + s.MustRegisterDataSource("ns_env", newDataEnv) // resources s.MustRegisterResource("ns_autogen_subdomain", newResourceAutogenSubdomain) diff --git a/website/docs/d/env.markdown b/website/docs/d/env.markdown new file mode 100644 index 0000000..a2fe9ea --- /dev/null +++ b/website/docs/d/env.markdown @@ -0,0 +1,40 @@ +--- +layout: "ns" +page_title: "Nullstone: ns_env" +sidebar_current: "docs-ns-env" +description: |- + Data source to read information about an environment. +--- + +# ns_env + +Data source to read information an environment. + +## Example Usage + +#### Basic example + +```hcl +data "ns_workspace" "this" {} + +data "ns_env" "this" { + stack_id = data.ns_workspace.this.stack_id + env_id = data.ns_workspace.this.env_id +} + +locals { + // env_type can be used to make decisions based on what type of environment + env_type = data.ns_env.this.type +} +``` + +## Arguments Reference + +* `stack_id` - (Required) ID of stack where the application resides in nullstone. +* `env_id` - (Required) ID of environment in nullstone. + +## Attributes Reference + +* `name` (string) - The name of the environment in Nullstone. +* `type` (string) - The type of environment in Nullstone. Possible values: `PipelineEnv`, `PreviewEnv`, `PreviewsSharedEnv`, `GlobalEnv`. +* `pipeline_order` (number) - [Only for `PipelineEnv`] A number that dictates which order the environment falls in the pipeline.