From 22ac99975821d38ad0c21b5dad6ef5afcb2fc417 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Fri, 22 Nov 2024 11:09:41 -0600 Subject: [PATCH 01/10] docs: add details to the docs for the provider itself --- docs/index.md | 117 ++++++++++++++++-- examples/provider/provider.tf | 12 +- .../provider/provider_with_allowed_tenants.tf | 3 + examples/provider/provider_with_auth_token.tf | 3 + .../resourcely_blueprint/resource.tf | 36 ++++++ .../resourcely_guardrail/resource.tf | 13 ++ internal/provider/provider.go | 2 +- templates/index.md.tmpl | 51 ++++++++ 8 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 examples/provider/provider_with_allowed_tenants.tf create mode 100644 examples/provider/provider_with_auth_token.tf create mode 100644 examples/resources/resourcely_blueprint/resource.tf create mode 100644 examples/resources/resourcely_guardrail/resource.tf create mode 100644 templates/index.md.tmpl diff --git a/docs/index.md b/docs/index.md index 80d2434..9c201cb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,25 +1,126 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "resourcely Provider" -subcategory: "" +page_title: "Provider: resourcely" description: |- - Configure Resourcely resources + Manage Resourcely blueprints, guardrails, global values, and more through Terraform. --- -# resourcely Provider +# RESOURCELY Provider -Configure Resourcely resources +The Resourcely provider is used to manage Resourcely blueprint, +guardrails, global values, and more through Terraform. The provider +needs to be configured with the proper credentials before it can be +used. ## Example Usage +Configure the Resourcely provider. + ```terraform +# Pin the source and version of the provider terraform { required_providers { resourcely = { - source = "Resourcely-Inc/resourcely" + source = "Resourcely-Inc/resourcely" + version = "~> 1.0" } } } + +# No provider configuration is required. See `Authentication and +# Configuration` below to learn how to provide your Resourcley API +# credentials. +provider "resourcely" { +} +``` + +Create a guardrail. + +```terraform +resource "resourcely_guardrail" "s3_bucket_naming_convention" { + name = "S3 Bucket Naming Convention" + description = "Ensures that all S3 Buckets comply with our standardized naming convention, promoting consistency and ease of identification across our AWS environments." + + cloud_provider = "PROVIDER_AMAZON" + category = "GUARDRAIL_BEST_PRACTICES" + + content = <<-EOT + GUARDRAIL "S3 Bucket Naming Convention" + WHEN aws_s3_bucket + REQUIRE bucket STARTS WITH "mycompany-" + EOT +} +``` + +Create a blueprint. + +```terraform +resource "resourcely_blueprint" "private_s3_bucket" { + name = "Private S3 Bucket" + description = "Creates a private, S3 bucket with configuration versioning." + + cloud_provider = "PROVIDER_AMAZON" + categories = ["BLUEPRINT_BLOB_STORAGE"] + + is_published = true + + content = <<-EOT + --- + constants: + __name: "{{ bucket }}_{{ __guid }}" + --- + resource "aws_s3_" "{{ __name }}" { + bucket = {{ bucket }} + } + + resource "aws_s3_bucket_public_access_block" "{{ __name }}" { + bucket = aws_s3_bucket.{{ __name }}.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true + } + + resource "aws_s3_bucket_ownership_controls" "{{ __name }}" { + bucket = aws_s3_bucket.{{ __name }}.id + + rule { + object_ownership = "BucketOwnerEnforced" + } + } + EOT +} +``` + +## Authentication and Configuration + +The provider requires a Resourcely API token to authenticate. It +expects the token to be provided through the `RESOURCELY_AUTH_TOKEN` +environment variable. Configure your Terraform runner to supply this +variable. + +You can generate the token from the [Resourcely Settings +page](https://portal.resourcely.io/settings/generate-api-token). Choose +the "Terraform Provider" role. + +You can also supply the token directly in the provider block. Ensure +that token is securely stored in a secret management system. Do not +hardcode it in the provider block. + +```terraform +provider "resourcely" { + auth_token = var.resourcely_auth_token +} +``` + +If your organization uses multiple tenants within Resourcely, you can +configure the `allowed_tenants` in the provider block to prevent +accidently mixing API keys between tenants. + +```terraform +provider "resourcely" { + allowed_tenants = ["MyCompany"] +} ``` @@ -29,4 +130,4 @@ terraform { - `allowed_tenants` (List of String) List of allowed tenant names (case-insensitive) to prevent accidently applying a configuration to the wrong one. - `auth_token` (String, Sensitive) Authorization token for Resourcely API. -- `host` (String) URI for Resourcely API. +- `host` (String) URI for Resourcely API. Defaults to 'https://api.resourcely.io'. diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 38daf75..d1f088f 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -1,7 +1,15 @@ +# Pin the source and version of the provider terraform { required_providers { resourcely = { - source = "Resourcely-Inc/resourcely" + source = "Resourcely-Inc/resourcely" + version = "~> 1.0" } } -} \ No newline at end of file +} + +# No provider configuration is required. See `Authentication and +# Configuration` below to learn how to provide your Resourcley API +# credentials. +provider "resourcely" { +} diff --git a/examples/provider/provider_with_allowed_tenants.tf b/examples/provider/provider_with_allowed_tenants.tf new file mode 100644 index 0000000..51d9534 --- /dev/null +++ b/examples/provider/provider_with_allowed_tenants.tf @@ -0,0 +1,3 @@ +provider "resourcely" { + allowed_tenants = ["MyCompany"] +} diff --git a/examples/provider/provider_with_auth_token.tf b/examples/provider/provider_with_auth_token.tf new file mode 100644 index 0000000..1961861 --- /dev/null +++ b/examples/provider/provider_with_auth_token.tf @@ -0,0 +1,3 @@ +provider "resourcely" { + auth_token = var.resourcely_auth_token +} diff --git a/examples/resources/resourcely_blueprint/resource.tf b/examples/resources/resourcely_blueprint/resource.tf new file mode 100644 index 0000000..55869b2 --- /dev/null +++ b/examples/resources/resourcely_blueprint/resource.tf @@ -0,0 +1,36 @@ +resource "resourcely_blueprint" "private_s3_bucket" { + name = "Private S3 Bucket" + description = "Creates a private, S3 bucket with configuration versioning." + + cloud_provider = "PROVIDER_AMAZON" + categories = ["BLUEPRINT_BLOB_STORAGE"] + + is_published = true + + content = <<-EOT + --- + constants: + __name: "{{ bucket }}_{{ __guid }}" + --- + resource "aws_s3_" "{{ __name }}" { + bucket = {{ bucket }} + } + + resource "aws_s3_bucket_public_access_block" "{{ __name }}" { + bucket = aws_s3_bucket.{{ __name }}.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true + } + + resource "aws_s3_bucket_ownership_controls" "{{ __name }}" { + bucket = aws_s3_bucket.{{ __name }}.id + + rule { + object_ownership = "BucketOwnerEnforced" + } + } + EOT +} diff --git a/examples/resources/resourcely_guardrail/resource.tf b/examples/resources/resourcely_guardrail/resource.tf new file mode 100644 index 0000000..a5c8f35 --- /dev/null +++ b/examples/resources/resourcely_guardrail/resource.tf @@ -0,0 +1,13 @@ +resource "resourcely_guardrail" "s3_bucket_naming_convention" { + name = "S3 Bucket Naming Convention" + description = "Ensures that all S3 Buckets comply with our standardized naming convention, promoting consistency and ease of identification across our AWS environments." + + cloud_provider = "PROVIDER_AMAZON" + category = "GUARDRAIL_BEST_PRACTICES" + + content = <<-EOT + GUARDRAIL "S3 Bucket Naming Convention" + WHEN aws_s3_bucket + REQUIRE bucket STARTS WITH "mycompany-" + EOT +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 48bcdf7..ac5f22e 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -51,7 +51,7 @@ func (p *ResourcelyProvider) Schema(ctx context.Context, req provider.SchemaRequ Description: "Configure Resourcely resources", Attributes: map[string]schema.Attribute{ "host": schema.StringAttribute{ - MarkdownDescription: "URI for Resourcely API.", + MarkdownDescription: "URI for Resourcely API. Defaults to 'https://api.resourcely.io'.", Optional: true, }, "auth_token": schema.StringAttribute{ diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl new file mode 100644 index 0000000..3d1eb67 --- /dev/null +++ b/templates/index.md.tmpl @@ -0,0 +1,51 @@ +--- +page_title: "Provider: resourcely" +description: |- + Manage Resourcely blueprints, guardrails, global values, and more through Terraform. +--- + +# {{ .ProviderShortName | upper }} Provider + +The Resourcely provider is used to manage Resourcely blueprint, +guardrails, global values, and more through Terraform. The provider +needs to be configured with the proper credentials before it can be +used. + +## Example Usage + +Configure the Resourcely provider. + +{{tffile "examples/provider/provider.tf"}} + +Create a guardrail. + +{{tffile "examples/resources/resourcely_guardrail/resource.tf"}} + +Create a blueprint. + +{{tffile "examples/resources/resourcely_blueprint/resource.tf"}} + +## Authentication and Configuration + +The provider requires a Resourcely API token to authenticate. It +expects the token to be provided through the `RESOURCELY_AUTH_TOKEN` +environment variable. Configure your Terraform runner to supply this +variable. + +You can generate the token from the [Resourcely Settings +page](https://portal.resourcely.io/settings/generate-api-token). Choose +the "Terraform Provider" role. + +You can also supply the token directly in the provider block. Ensure +that token is securely stored in a secret management system. Do not +hardcode it in the provider block. + +{{tffile "examples/provider/provider_with_auth_token.tf"}} + +If your organization uses multiple tenants within Resourcely, you can +configure the `allowed_tenants` in the provider block to prevent +accidently mixing API keys between tenants. + +{{tffile "examples/provider/provider_with_allowed_tenants.tf"}} + +{{ .SchemaMarkdown | trimspace }} From 8b6ac14d4e93eb09553728c957e216f36f8aa0ce Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Fri, 22 Nov 2024 11:10:54 -0600 Subject: [PATCH 02/10] examples: remove scaffolding examples --- examples/data-sources/scaffolding_example/data-source.tf | 3 --- examples/resources/scaffolding_example/resource.tf | 4 ---- 2 files changed, 7 deletions(-) delete mode 100644 examples/data-sources/scaffolding_example/data-source.tf delete mode 100644 examples/resources/scaffolding_example/resource.tf diff --git a/examples/data-sources/scaffolding_example/data-source.tf b/examples/data-sources/scaffolding_example/data-source.tf deleted file mode 100644 index f4f73ef..0000000 --- a/examples/data-sources/scaffolding_example/data-source.tf +++ /dev/null @@ -1,3 +0,0 @@ -data "github_team" "example" { - configurable_attribute = "some-value" -} \ No newline at end of file diff --git a/examples/resources/scaffolding_example/resource.tf b/examples/resources/scaffolding_example/resource.tf deleted file mode 100644 index 39193b6..0000000 --- a/examples/resources/scaffolding_example/resource.tf +++ /dev/null @@ -1,4 +0,0 @@ -# for more information on Authoring Your Own Blueprints https://docs.resourcely.com/getting-started/using-resourcely/setting-up-blueprints/authoring-your-own-blueprints -resource "resourcely_blueprint" "example" { - configurable_attribute = "some-value" -} From a819393cd303de073c95d1d0e6c7a7e1af279d22 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Fri, 22 Nov 2024 11:39:28 -0600 Subject: [PATCH 03/10] docs: add details to the blueprint resource docs --- docs/resources/blueprint.md | 85 +++++++++++++++---- .../resources/resourcely_blueprint/import.sh | 1 + internal/provider/blueprint_resource.go | 24 +++--- templates/resources/blueprint.md.tmpl | 22 +++++ 4 files changed, 104 insertions(+), 28 deletions(-) create mode 100644 examples/resources/resourcely_blueprint/import.sh create mode 100644 templates/resources/blueprint.md.tmpl diff --git a/docs/resources/blueprint.md b/docs/resources/blueprint.md index be3e2e6..b46d415 100644 --- a/docs/resources/blueprint.md +++ b/docs/resources/blueprint.md @@ -1,16 +1,65 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_blueprint Resource - terraform-provider-resourcely" subcategory: "" description: |- - A Resourcely Blueprint + A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: + Define which options are available for properties of your resource(s).Apply gaurdrails to your resource(s) to prevent misconfiguration.Define what information to collect from your developers before provisioning the resource. + One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. + The template is specified using Resourcely's TFT templating language. See the Authoring Your Own Blueprints https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints docs for details about TFT. The Resourcely Foundry https://portal.resourcely.io/foundry?mode=blueprint provides an IDE to assist with authoring the template. --- # resourcely_blueprint (Resource) -A Resourcely Blueprint +A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: +- Define which options are available for properties of your resource(s). +- Apply gaurdrails to your resource(s) to prevent misconfiguration. +- Define what information to collect from your developers before provisioning the resource. +One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. + +The template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template. + +## Example Usage + +```terraform +resource "resourcely_blueprint" "private_s3_bucket" { + name = "Private S3 Bucket" + description = "Creates a private, S3 bucket with configuration versioning." + + cloud_provider = "PROVIDER_AMAZON" + categories = ["BLUEPRINT_BLOB_STORAGE"] + + is_published = true + + content = <<-EOT + --- + constants: + __name: "{{ bucket }}_{{ __guid }}" + --- + resource "aws_s3_" "{{ __name }}" { + bucket = {{ bucket }} + } + + resource "aws_s3_bucket_public_access_block" "{{ __name }}" { + bucket = aws_s3_bucket.{{ __name }}.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true + } + + resource "aws_s3_bucket_ownership_controls" "{{ __name }}" { + bucket = aws_s3_bucket.{{ __name }}.id + + rule { + object_ownership = "BucketOwnerEnforced" + } + } + EOT +} +``` ## Schema @@ -18,23 +67,29 @@ A Resourcely Blueprint ### Required - `cloud_provider` (String) The cloud provider that this blueprint targets. Can be one of `PROVIDER_AMAZON`, `PROVIDER_AZURE`, `PROVIDER_CONDUCTORONE`, `PROVIDER_DATABRICKS`, `PROVIDER_DATADOG`, `PROVIDER_GITHUB`, `PROVIDER_GITLAB`, `PROVIDER_GOOGLE`, `PROVIDER_HYPERV`, `PROVIDER_IBM`, `PROVIDER_JUMPCLOUD`, `PROVIDER_KUBERNETES`, `PROVIDER_OKTA`, `PROVIDER_ORACLE`, `PROVIDER_RESOURCELY`, `PROVIDER_SNOWFLAKE`, `PROVIDER_SPACELIFT`, `PROVIDER_VMWARE`, `PROVIDER_OTHER` -- `content` (String) -- `name` (String) +- `content` (String) The templated Terraform configuration specified using Resourcely's TFT format. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the content. +- `name` (String) The name of the blueprint. ### Optional - `categories` (Set of String) The category to assign to this blueprint. Can be one of `BLUEPRINT_ASYNC_PROCESSING`, `BLUEPRINT_BLOB_STORAGE`, `BLUEPRINT_COMPUTE`, `BLUEPRINT_CONTAINERIZATION`, `BLUEPRINT_DATABASE`, `BLUEPRINT_GITHUB_REPO`, `BLUEPRINT_GITHUB_REPO_TEAM`, `BLUEPRINT_IAM`, `BLUEPRINT_LOGS_AND_METRICS`, `BLUEPRINT_NETWORKING`, `BLUEPRINT_SERVERLESS_COMPUTE` -- `description` (String) -- `excluded_context_question_series` (Set of String) series_id for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories -- `guidance` (String) -- `is_published` (Boolean) A published blueprint is available for use by developers to create resources through the Resourcely portal. - -If left unset, the blueprint will start as unpublished, and you may safely change this property in the Resourcely portal. -- `labels` (Set of String) +- `description` (String) A description of the blueprint's purpose or functionality. +- `excluded_context_question_series` (Set of String) The series_ids for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories +- `guidance` (String) Guidance to help your users know when and how to use this blueprint. +- `is_published` (Boolean) A published blueprint is available for use by developers to create resources through the Resourcely portal. If left unset, the blueprint will start as unpublished, and you may safely change this property in the Resourcely portal. +- `labels` (Set of String) Additional keywords to help your users discover this blueprint. - `scope` (String) ### Read-Only -- `id` (String) UUID for this version. -- `series_id` (String) UUID for the blueprint -- `version` (Number) Specific version of the blueprint +- `id` (String) UUID for the current version of the blueprint. +- `series_id` (String) UUID for the blueprint. +- `version` (Number) Incrementing version number for the current version of the blueprint. + +## Import + +A blueprint can be imported using its series_id. + +```shell +terraform import resourcely_blueprint.example 00000000-00000000-00000000-00000000 +``` diff --git a/examples/resources/resourcely_blueprint/import.sh b/examples/resources/resourcely_blueprint/import.sh new file mode 100644 index 0000000..5d3a4af --- /dev/null +++ b/examples/resources/resourcely_blueprint/import.sh @@ -0,0 +1 @@ +terraform import resourcely_blueprint.example 00000000-00000000-00000000-00000000 diff --git a/internal/provider/blueprint_resource.go b/internal/provider/blueprint_resource.go index c5fc67f..2faaca0 100644 --- a/internal/provider/blueprint_resource.go +++ b/internal/provider/blueprint_resource.go @@ -51,23 +51,21 @@ func (r *BlueprintResource) Schema( resp *resource.SchemaResponse, ) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A Resourcely Blueprint", - + MarkdownDescription: "A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to:\n\n- Define which options are available for properties of your resource(s).\n- Apply gaurdrails to your resource(s) to prevent misconfiguration.\n- Define what information to collect from your developers before provisioning the resource.\n\nOne a blueprint is configured and published, it becomes available for use in your Resourcely service catalog.\n\nThe template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of the blueprint.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the blueprint", + MarkdownDescription: "UUID for the blueprint.", Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the blueprint", + MarkdownDescription: "Incrementing version number for the current version of the blueprint.", Computed: true, }, "scope": schema.StringAttribute{ @@ -78,11 +76,11 @@ func (r *BlueprintResource) Schema( }, }, "name": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The name of the blueprint.", Required: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "A description of the blueprint's purpose or functionality.", Default: stringdefault.StaticString(""), Computed: true, Optional: true, @@ -116,18 +114,18 @@ func (r *BlueprintResource) Schema( }, }, "content": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The templated Terraform configuration specified using Resourcely's TFT format. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the content.", Required: true, }, "guidance": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "Guidance to help your users know when and how to use this blueprint.", Default: stringdefault.StaticString(""), Computed: true, Optional: true, }, "labels": schema.SetAttribute{ ElementType: basetypes.StringType{}, - MarkdownDescription: "", + MarkdownDescription: "Additional keywords to help your users discover this blueprint.", Default: setdefault.StaticValue(types.SetValueMust(types.StringType, nil)), Computed: true, Optional: true, @@ -159,7 +157,7 @@ func (r *BlueprintResource) Schema( "is_published": schema.BoolAttribute{ Computed: true, Optional: true, - MarkdownDescription: "A published blueprint is available for use by developers to create resources through the Resourcely portal.\n\nIf left unset, the blueprint will start as unpublished, and you may safely change this property in the Resourcely portal.", + MarkdownDescription: "A published blueprint is available for use by developers to create resources through the Resourcely portal. If left unset, the blueprint will start as unpublished, and you may safely change this property in the Resourcely portal.", PlanModifiers: []planmodifier.Bool{ boolplanmodifier.UseStateForUnknown(), }, @@ -169,7 +167,7 @@ func (r *BlueprintResource) Schema( ElementType: basetypes.StringType{}, Computed: true, Optional: true, - MarkdownDescription: "series_id for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories", + MarkdownDescription: "The series_ids for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories", }, }, } diff --git a/templates/resources/blueprint.md.tmpl b/templates/resources/blueprint.md.tmpl new file mode 100644 index 0000000..7870a47 --- /dev/null +++ b/templates/resources/blueprint.md.tmpl @@ -0,0 +1,22 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +{{ tffile .ExampleFile }} + +{{ .SchemaMarkdown | trimspace }} + +## Import + +A blueprint can be imported using its series_id. + +{{codefile "shell" .ImportFile }} From c6d6e2063c1d7e95f23862ea8e51eb5fff22c42a Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Fri, 22 Nov 2024 12:02:53 -0600 Subject: [PATCH 04/10] blueprint datasource: mark is_published as read only --- internal/provider/blueprint_data_source.go | 24 ++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/internal/provider/blueprint_data_source.go b/internal/provider/blueprint_data_source.go index e551330..3c9a740 100644 --- a/internal/provider/blueprint_data_source.go +++ b/internal/provider/blueprint_data_source.go @@ -29,12 +29,11 @@ func (d *BlueprintDataSource) Metadata(_ context.Context, req datasource.Metadat func (d *BlueprintDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A resourcely blueprint", + MarkdownDescription: "A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to:\n\n- Define which options are available for properties of your resource(s).\n- Apply gaurdrails to your resource(s) to prevent misconfiguration.\n- Define what information to collect from your developers before provisioning the resource.\n\nOne a blueprint is configured and published, it becomes available for use in your Resourcely service catalog.\n\nThe template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of the blueprint.", Computed: true, }, "series_id": schema.StringAttribute{ @@ -42,51 +41,50 @@ func (d *BlueprintDataSource) Schema(_ context.Context, _ datasource.SchemaReque Required: true, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the blueprint", + MarkdownDescription: "Increment version number for the current version of the blueprint.", Computed: true, }, "scope": schema.StringAttribute{ Computed: true, }, "name": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The name of the blueprint.", Computed: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "A description of the blueprints's purpose or functionality.", Computed: true, }, "cloud_provider": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The cloud provider that this blueprint targets.", Computed: true, }, "content": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The templated Terraform configuration specified using Resourcely's TFT format.", Computed: true, }, "guidance": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "Guidance to help your users know when and how to use this blueprint.", Computed: true, }, "categories": schema.SetAttribute{ ElementType: basetypes.StringType{}, Computed: true, - MarkdownDescription: "", + MarkdownDescription: "The category to assign to this blueprint.", }, "labels": schema.SetAttribute{ ElementType: basetypes.StringType{}, Computed: true, - MarkdownDescription: "", + MarkdownDescription: "Additional keywords to help your users discover this blueprint.", }, "is_published": schema.BoolAttribute{ Computed: true, - Optional: true, MarkdownDescription: "A published blueprint is available for use by developers to create resources through the Resourcely portal.", }, "excluded_context_question_series": schema.SetAttribute{ ElementType: basetypes.StringType{}, Computed: true, - MarkdownDescription: "series_id for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories", + MarkdownDescription: "The series_ids for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories", }, }, } From e59fed11be67fa9a04e9b0e620367edaa3769e14 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Fri, 22 Nov 2024 12:05:04 -0600 Subject: [PATCH 05/10] docs: add details to the blueprint data source docs --- docs/data-sources/blueprint.md | 47 ++++++++++++------- .../resourcely_blueprint/data-source.tf | 3 ++ templates/data-sources/blueprint.md.tmpl | 16 +++++++ 3 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 examples/data-sources/resourcely_blueprint/data-source.tf create mode 100644 templates/data-sources/blueprint.md.tmpl diff --git a/docs/data-sources/blueprint.md b/docs/data-sources/blueprint.md index d91ee12..cd1c915 100644 --- a/docs/data-sources/blueprint.md +++ b/docs/data-sources/blueprint.md @@ -1,16 +1,32 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_blueprint Data Source - terraform-provider-resourcely" subcategory: "" description: |- - A resourcely blueprint + A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: + Define which options are available for properties of your resource(s).Apply gaurdrails to your resource(s) to prevent misconfiguration.Define what information to collect from your developers before provisioning the resource. + One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. + The template is specified using Resourcely's TFT templating language. See the Authoring Your Own Blueprints https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints docs for details about TFT. The Resourcely Foundry https://portal.resourcely.io/foundry?mode=blueprint provides an IDE to assist with authoring the template. --- # resourcely_blueprint (Data Source) -A resourcely blueprint +A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: +- Define which options are available for properties of your resource(s). +- Apply gaurdrails to your resource(s) to prevent misconfiguration. +- Define what information to collect from your developers before provisioning the resource. +One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. + +The template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template. + +## Example Usage + +```terraform +data "resourcely_blueprint" "example" { + series_id = "00000000-00000000-00000000-00000000" +} +``` ## Schema @@ -19,20 +35,17 @@ A resourcely blueprint - `series_id` (String) UUID for the blueprint -### Optional - -- `is_published` (Boolean) A published blueprint is available for use by developers to create resources through the Resourcely portal. - ### Read-Only -- `categories` (Set of String) -- `cloud_provider` (String) -- `content` (String) -- `description` (String) -- `excluded_context_question_series` (Set of String) series_id for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories -- `guidance` (String) -- `id` (String) UUID for this version. -- `labels` (Set of String) -- `name` (String) +- `categories` (Set of String) The category to assign to this blueprint. +- `cloud_provider` (String) The cloud provider that this blueprint targets. +- `content` (String) The templated Terraform configuration specified using Resourcely's TFT format. +- `description` (String) A description of the blueprints's purpose or functionality. +- `excluded_context_question_series` (Set of String) The series_ids for context questions that won't be used with this blueprint, even if this blueprint matches the context questions' blueprint_categories +- `guidance` (String) Guidance to help your users know when and how to use this blueprint. +- `id` (String) UUID for the current version of the blueprint. +- `is_published` (Boolean) A published blueprint is available for use by developers to create resources through the Resourcely portal. +- `labels` (Set of String) Additional keywords to help your users discover this blueprint. +- `name` (String) The name of the blueprint. - `scope` (String) -- `version` (Number) Specific version of the blueprint +- `version` (Number) Increment version number for the current version of the blueprint. diff --git a/examples/data-sources/resourcely_blueprint/data-source.tf b/examples/data-sources/resourcely_blueprint/data-source.tf new file mode 100644 index 0000000..8b88693 --- /dev/null +++ b/examples/data-sources/resourcely_blueprint/data-source.tf @@ -0,0 +1,3 @@ +data "resourcely_blueprint" "example" { + series_id = "00000000-00000000-00000000-00000000" +} diff --git a/templates/data-sources/blueprint.md.tmpl b/templates/data-sources/blueprint.md.tmpl new file mode 100644 index 0000000..be3ff70 --- /dev/null +++ b/templates/data-sources/blueprint.md.tmpl @@ -0,0 +1,16 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +{{ tffile .ExampleFile }} + +{{ .SchemaMarkdown | trimspace }} From 0328617bf7ed326a4af42a60358b6471432af928 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Mon, 25 Nov 2024 11:18:56 -0600 Subject: [PATCH 06/10] docs: add details to the guardrail resource and data source docs --- docs/data-sources/guardrail.md | 42 +++++---- docs/resources/guardrail.md | 86 +++++++++++++++---- .../resourcely_guardrail/data-source.tf | 3 + .../resources/resourcely_guardrail/import.sh | 1 + .../resource_with_template.tf | 13 +++ internal/provider/guardrail_data_source.go | 26 +++--- internal/provider/guardrail_resource.go | 26 +++--- templates/data-sources/guardrail.md.tmpl | 16 ++++ templates/resources/guardrail.md.tmpl | 31 +++++++ 9 files changed, 184 insertions(+), 60 deletions(-) create mode 100644 examples/data-sources/resourcely_guardrail/data-source.tf create mode 100644 examples/resources/resourcely_guardrail/import.sh create mode 100644 examples/resources/resourcely_guardrail/resource_with_template.tf create mode 100644 templates/data-sources/guardrail.md.tmpl create mode 100644 templates/resources/guardrail.md.tmpl diff --git a/docs/data-sources/guardrail.md b/docs/data-sources/guardrail.md index 96d9e95..2ce2d6a 100644 --- a/docs/data-sources/guardrail.md +++ b/docs/data-sources/guardrail.md @@ -1,36 +1,46 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_guardrail Data Source - terraform-provider-resourcely" subcategory: "" description: |- - A resourcely guardrail + A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. Some examples of guardrails include: + Require approval for making a public S3 bucketRestrict the allowed compute instance types or images + Guardrails are specified using the Really policy language https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails. --- # resourcely_guardrail (Data Source) -A resourcely guardrail +A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. Some examples of guardrails include: +- Require approval for making a public S3 bucket +- Restrict the allowed compute instance types or images +Guardrails are specified using the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). + +## Example Usage + +```terraform +data "resourcely_guardrail" "example" { + series_id = "00000000-00000000-00000000-00000000" +} +``` ## Schema ### Required -- `series_id` (String) UUID for the guardrail +- `series_id` (String) UUID for the guardrail. ### Read-Only -- `category` (String) -- `cloud_provider` (String) -- `content` (String) -- `description` (String) -- `guardrail_template_inputs` (String) A JSON encoding of values for the guardrail template inputs. - -Example: `guardrail_template_inputs = jsonencode({inputOne = "value one"})` -- `guardrail_template_series_id` (String) The series id of the guardrail template used to render the policies -- `id` (String) UUID for this version. -- `name` (String) +- `category` (String) The category of this guardrail. +- `cloud_provider` (String) The cloud provider that this guardrail targets. +- `content` (String) The guardrail policy written in the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). +- `description` (String) A description of the guardrail's purpose or policy. +- `guardrail_template_inputs` (String) A JSON encoding of values for the guardrail template inputs.` +- `guardrail_template_series_id` (String) The series id of the guardrail template used to render the policy. +- `id` (String) UUID for the current version of this guar. +- `name` (String) The name of the guardrail. - `scope` (String) -- `state` (String) -- `version` (Number) Specific version of the guardrail +- `state` (String) The [state](https://docs.resourcely.io/build/setting-up-guardrails/releasing-guardrails#guardrail-status) of the guardrail. +- `version` (Number) Incrementing version number for this current version of the guardrail. diff --git a/docs/resources/guardrail.md b/docs/resources/guardrail.md index c93db1e..18adf8a 100644 --- a/docs/resources/guardrail.md +++ b/docs/resources/guardrail.md @@ -1,39 +1,93 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_guardrail Resource - terraform-provider-resourcely" subcategory: "" description: |- - A resourcely guardrail + A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. + Some examples of guardrails include: + Require approval for making a public S3 bucketRestrict the allowed compute instance types or images + Guardrails are specified using the Really policy language https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails. --- # resourcely_guardrail (Resource) -A resourcely guardrail +A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. +Some examples of guardrails include: +- Require approval for making a public S3 bucket +- Restrict the allowed compute instance types or images + +Guardrails are specified using the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). + +## Example Usage + +Create a guardrail using the [Really policy langauge](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). + +```terraform +resource "resourcely_guardrail" "s3_bucket_naming_convention" { + name = "S3 Bucket Naming Convention" + description = "Ensures that all S3 Buckets comply with our standardized naming convention, promoting consistency and ease of identification across our AWS environments." + + cloud_provider = "PROVIDER_AMAZON" + category = "GUARDRAIL_BEST_PRACTICES" + + content = <<-EOT + GUARDRAIL "S3 Bucket Naming Convention" + WHEN aws_s3_bucket + REQUIRE bucket STARTS WITH "mycompany-" + EOT +} +``` + +This resource also supports creating a guardrail from a Resourcely +Guardrail Template. Instead of specifying the `content`, specify the +`guardrail_template_series_id` and `guardrail_template_inputs` +instead. + +```terraform +resource "resourcely_guardrail" "s3_bucket_naming_convention_from_template" { + name = "S3 Bucket Naming Convention" + description = "Ensures that all S3 Buckets comply with our standardized naming convention, promoting consistency and ease of identification across our AWS environments." + + cloud_provider = "PROVIDER_AMAZON" + category = "GUARDRAIL_BEST_PRACTICES" + + guardrail_template_series_id = "4909a93c-b248-4e5a-bff5-7cc101702351" + guardrail_template_inputs = jsonencode({ + prefix = "mycompany-" + approver = "default" + }) +} +``` ## Schema ### Required -- `category` (String) The category to assign to the guardrail. Can be one of `GUARDRAIL_ACCESS_CONTROL`, `GUARDRAIL_BEST_PRACTICES`, `GUARDRAIL_CHANGE_MANAGEMENT`, `GUARDRAIL_COST_EFFICIENCY`, `GUARDRAIL_ENCRYPTION`, `GUARDRAIL_GLOBALIZATION`, `GUARDRAIL_IAM`, `GUARDRAIL_LOGGING`, `GUARDRAIL_MODULE_INPUTS`, `GUARDRAIL_PRIVACY_COMPLIANCE`, `GUARDRAIL_RELIABILITY`, `GUARDRAIL_STORAGE_AND_SCALE` -- `cloud_provider` (String) The cloud provider that this guardrail targets. Can be one of `PROVIDER_AMAZON`, `PROVIDER_AZURE`, `PROVIDER_CONDUCTORONE`, `PROVIDER_DATABRICKS`, `PROVIDER_DATADOG`, `PROVIDER_GITHUB`, `PROVIDER_GITLAB`, `PROVIDER_GOOGLE`, `PROVIDER_HYPERV`, `PROVIDER_IBM`,`PROVIDER_JUMPCLOUD`, `PROVIDER_KUBERNETES`, `PROVIDER_OKTA`, `PROVIDER_ORACLE`, `PROVIDER_RESOURCELY`, `PROVIDER_SNOWFLAKE`, `PROVIDER_SPACELIFT`, `PROVIDER_VMWARE`, `PROVIDER_OTHER` -- `name` (String) Name to associate with the guardrail +- `category` (String) The category to assign to this guardrail. Can be one of `GUARDRAIL_ACCESS_CONTROL`, `GUARDRAIL_BEST_PRACTICES`, `GUARDRAIL_CHANGE_MANAGEMENT`, `GUARDRAIL_COST_EFFICIENCY`, `GUARDRAIL_ENCRYPTION`, `GUARDRAIL_GLOBALIZATION`, `GUARDRAIL_IAM`, `GUARDRAIL_LOGGING`, `GUARDRAIL_MODULE_INPUTS`, `GUARDRAIL_PRIVACY_COMPLIANCE`, `GUARDRAIL_RELIABILITY`, `GUARDRAIL_STORAGE_AND_SCALE`. +- `cloud_provider` (String) The cloud provider that this guardrail targets. Can be one of `PROVIDER_AMAZON`, `PROVIDER_AZURE`, `PROVIDER_CONDUCTORONE`, `PROVIDER_DATABRICKS`, `PROVIDER_DATADOG`, `PROVIDER_GITHUB`, `PROVIDER_GITLAB`, `PROVIDER_GOOGLE`, `PROVIDER_HYPERV`, `PROVIDER_IBM`,`PROVIDER_JUMPCLOUD`, `PROVIDER_KUBERNETES`, `PROVIDER_OKTA`, `PROVIDER_ORACLE`, `PROVIDER_RESOURCELY`, `PROVIDER_SNOWFLAKE`, `PROVIDER_SPACELIFT`, `PROVIDER_VMWARE`, `PROVIDER_OTHER`. +- `name` (String) The name of the guardrail. ### Optional -- `content` (String) The content of the guardrail, written in Resourcely's Really language -- `description` (String) Description of what the guardrail applies to -- `guardrail_template_inputs` (String) A JSON encoding of values for the guardrail template inputs. - -Example: `guardrail_template_inputs = jsonencode({inputOne = "value one"})` -- `guardrail_template_series_id` (String) The series id of the guardrail template used to render the policies +- `content` (String) The guardrail policy written in the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). Must specify exactly one of `content` or `guardrail_template_series_id`. +- `description` (String) A description of the guardrail's purpose or policy. +- `guardrail_template_inputs` (String) A JSON encoding of values for the guardrail template inputs. Required if `guardrail_template_series_id` is used. Example: `guardrail_template_inputs = jsonencode({inputOne = "value one"})` +- `guardrail_template_series_id` (String) The series id of the guardrail template used to render the policy. Must specify exactly one of `guardrail_template_series_id` or `content`. - `scope` (String) -- `state` (String) The state to set the guardrail to. Can be one of `GUARDRAIL_STATE_INACTIVE`, `GUARDRAIL_STATE_EVALUATE_ONLY`, `GUARDRAIL_STATE_ACTIVE`. If not provided state is set to `GUARDRAIL_STATE_ACTIVE` +- `state` (String) The [state](https://docs.resourcely.io/build/setting-up-guardrails/releasing-guardrails#guardrail-status) of the guardrail. Can be one of `GUARDRAIL_STATE_INACTIVE`, `GUARDRAIL_STATE_EVALUATE_ONLY`, `GUARDRAIL_STATE_ACTIVE`. If not provided state is set to `GUARDRAIL_STATE_ACTIVE`. ### Read-Only -- `id` (String) UUID for this version. -- `series_id` (String) UUID for the guardrail -- `version` (Number) Specific version of the guardrail +- `id` (String) UUID for the current version of the guardrail. +- `series_id` (String) UUID for the guardrail. +- `version` (Number) Incrementing version number for the current version of the guardrail. + +## Import + +A guardrail can be imported using its series_id. + +```shell +terraform import resourcely_guardrail.example 00000000-00000000-00000000-00000000 +``` diff --git a/examples/data-sources/resourcely_guardrail/data-source.tf b/examples/data-sources/resourcely_guardrail/data-source.tf new file mode 100644 index 0000000..68f165c --- /dev/null +++ b/examples/data-sources/resourcely_guardrail/data-source.tf @@ -0,0 +1,3 @@ +data "resourcely_guardrail" "example" { + series_id = "00000000-00000000-00000000-00000000" +} diff --git a/examples/resources/resourcely_guardrail/import.sh b/examples/resources/resourcely_guardrail/import.sh new file mode 100644 index 0000000..332cb1b --- /dev/null +++ b/examples/resources/resourcely_guardrail/import.sh @@ -0,0 +1 @@ +terraform import resourcely_guardrail.example 00000000-00000000-00000000-00000000 diff --git a/examples/resources/resourcely_guardrail/resource_with_template.tf b/examples/resources/resourcely_guardrail/resource_with_template.tf new file mode 100644 index 0000000..fbc09b1 --- /dev/null +++ b/examples/resources/resourcely_guardrail/resource_with_template.tf @@ -0,0 +1,13 @@ +resource "resourcely_guardrail" "s3_bucket_naming_convention_from_template" { + name = "S3 Bucket Naming Convention" + description = "Ensures that all S3 Buckets comply with our standardized naming convention, promoting consistency and ease of identification across our AWS environments." + + cloud_provider = "PROVIDER_AMAZON" + category = "GUARDRAIL_BEST_PRACTICES" + + guardrail_template_series_id = "4909a93c-b248-4e5a-bff5-7cc101702351" + guardrail_template_inputs = jsonencode({ + prefix = "mycompany-" + approver = "default" + }) +} diff --git a/internal/provider/guardrail_data_source.go b/internal/provider/guardrail_data_source.go index ec70d3f..4b2096e 100644 --- a/internal/provider/guardrail_data_source.go +++ b/internal/provider/guardrail_data_source.go @@ -29,20 +29,18 @@ func (d *GuardrailDataSource) Metadata(ctx context.Context, req datasource.Metad func (d *GuardrailDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A resourcely guardrail", - + MarkdownDescription: "A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. Some examples of guardrails include:\n\n- Require approval for making a public S3 bucket\n- Restrict the allowed compute instance types or images\n\nGuardrails are specified using the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails).", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of this guar.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the guardrail", + MarkdownDescription: "UUID for the guardrail.", Required: true, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the guardrail", + MarkdownDescription: "Incrementing version number for this current version of the guardrail.", Computed: true, }, "scope": schema.StringAttribute{ @@ -50,36 +48,36 @@ func (d *GuardrailDataSource) Schema(ctx context.Context, req datasource.SchemaR Computed: true, }, "name": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The name of the guardrail.", Computed: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "A description of the guardrail's purpose or policy.", Computed: true, }, "cloud_provider": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The cloud provider that this guardrail targets.", Computed: true, }, "category": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The category of this guardrail.", Computed: true, }, "state": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The [state](https://docs.resourcely.io/build/setting-up-guardrails/releasing-guardrails#guardrail-status) of the guardrail.", Computed: true, }, "content": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The guardrail policy written in the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails).", Computed: true, }, "guardrail_template_series_id": schema.StringAttribute{ - MarkdownDescription: "The series id of the guardrail template used to render the policies", + MarkdownDescription: "The series id of the guardrail template used to render the policy.", Computed: true, }, "guardrail_template_inputs": schema.StringAttribute{ CustomType: jsontypes.NormalizedType{}, - MarkdownDescription: "A JSON encoding of values for the guardrail template inputs.\n\nExample: `guardrail_template_inputs = jsonencode({inputOne = \"value one\"})`", + MarkdownDescription: "A JSON encoding of values for the guardrail template inputs.`", Computed: true, }, }, diff --git a/internal/provider/guardrail_resource.go b/internal/provider/guardrail_resource.go index bf0cbd8..1210b9c 100644 --- a/internal/provider/guardrail_resource.go +++ b/internal/provider/guardrail_resource.go @@ -48,23 +48,21 @@ func (r *GuardrailResource) Schema( resp *resource.SchemaResponse, ) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A resourcely guardrail", - + MarkdownDescription: "A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated.\n\nSome examples of guardrails include:\n\n- Require approval for making a public S3 bucket\n- Restrict the allowed compute instance types or images\n\nGuardrails are specified using the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails).", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of the guardrail.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the guardrail", + MarkdownDescription: "UUID for the guardrail.", Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the guardrail", + MarkdownDescription: "Incrementing version number for the current version of the guardrail.", Computed: true, }, "scope": schema.StringAttribute{ @@ -75,17 +73,17 @@ func (r *GuardrailResource) Schema( }, }, "name": schema.StringAttribute{ - MarkdownDescription: "Name to associate with the guardrail", + MarkdownDescription: "The name of the guardrail.", Required: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "Description of what the guardrail applies to", + MarkdownDescription: "A description of the guardrail's purpose or policy.", Default: stringdefault.StaticString(""), Computed: true, Optional: true, }, "cloud_provider": schema.StringAttribute{ - MarkdownDescription: "The cloud provider that this guardrail targets. Can be one of `PROVIDER_AMAZON`, `PROVIDER_AZURE`, `PROVIDER_CONDUCTORONE`, `PROVIDER_DATABRICKS`, `PROVIDER_DATADOG`, `PROVIDER_GITHUB`, `PROVIDER_GITLAB`, `PROVIDER_GOOGLE`, `PROVIDER_HYPERV`, `PROVIDER_IBM`,`PROVIDER_JUMPCLOUD`, `PROVIDER_KUBERNETES`, `PROVIDER_OKTA`, `PROVIDER_ORACLE`, `PROVIDER_RESOURCELY`, `PROVIDER_SNOWFLAKE`, `PROVIDER_SPACELIFT`, `PROVIDER_VMWARE`, `PROVIDER_OTHER`", + MarkdownDescription: "The cloud provider that this guardrail targets. Can be one of `PROVIDER_AMAZON`, `PROVIDER_AZURE`, `PROVIDER_CONDUCTORONE`, `PROVIDER_DATABRICKS`, `PROVIDER_DATADOG`, `PROVIDER_GITHUB`, `PROVIDER_GITLAB`, `PROVIDER_GOOGLE`, `PROVIDER_HYPERV`, `PROVIDER_IBM`,`PROVIDER_JUMPCLOUD`, `PROVIDER_KUBERNETES`, `PROVIDER_OKTA`, `PROVIDER_ORACLE`, `PROVIDER_RESOURCELY`, `PROVIDER_SNOWFLAKE`, `PROVIDER_SPACELIFT`, `PROVIDER_VMWARE`, `PROVIDER_OTHER`.", Required: true, Validators: []validator.String{ stringvalidator.OneOf( @@ -112,7 +110,7 @@ func (r *GuardrailResource) Schema( }, }, "category": schema.StringAttribute{ - MarkdownDescription: "The category to assign to the guardrail. Can be one of `GUARDRAIL_ACCESS_CONTROL`, `GUARDRAIL_BEST_PRACTICES`, `GUARDRAIL_CHANGE_MANAGEMENT`, `GUARDRAIL_COST_EFFICIENCY`, `GUARDRAIL_ENCRYPTION`, `GUARDRAIL_GLOBALIZATION`, `GUARDRAIL_IAM`, `GUARDRAIL_LOGGING`, `GUARDRAIL_MODULE_INPUTS`, `GUARDRAIL_PRIVACY_COMPLIANCE`, `GUARDRAIL_RELIABILITY`, `GUARDRAIL_STORAGE_AND_SCALE`", + MarkdownDescription: "The category to assign to this guardrail. Can be one of `GUARDRAIL_ACCESS_CONTROL`, `GUARDRAIL_BEST_PRACTICES`, `GUARDRAIL_CHANGE_MANAGEMENT`, `GUARDRAIL_COST_EFFICIENCY`, `GUARDRAIL_ENCRYPTION`, `GUARDRAIL_GLOBALIZATION`, `GUARDRAIL_IAM`, `GUARDRAIL_LOGGING`, `GUARDRAIL_MODULE_INPUTS`, `GUARDRAIL_PRIVACY_COMPLIANCE`, `GUARDRAIL_RELIABILITY`, `GUARDRAIL_STORAGE_AND_SCALE`.", Required: true, Validators: []validator.String{ stringvalidator.OneOf( @@ -132,7 +130,7 @@ func (r *GuardrailResource) Schema( }, }, "state": schema.StringAttribute{ - MarkdownDescription: "The state to set the guardrail to. Can be one of `GUARDRAIL_STATE_INACTIVE`, `GUARDRAIL_STATE_EVALUATE_ONLY`, `GUARDRAIL_STATE_ACTIVE`. If not provided state is set to `GUARDRAIL_STATE_ACTIVE`", + MarkdownDescription: "The [state](https://docs.resourcely.io/build/setting-up-guardrails/releasing-guardrails#guardrail-status) of the guardrail. Can be one of `GUARDRAIL_STATE_INACTIVE`, `GUARDRAIL_STATE_EVALUATE_ONLY`, `GUARDRAIL_STATE_ACTIVE`. If not provided state is set to `GUARDRAIL_STATE_ACTIVE`.", Optional: true, Computed: true, Default: stringdefault.StaticString("GUARDRAIL_STATE_ACTIVE"), @@ -145,19 +143,19 @@ func (r *GuardrailResource) Schema( }, }, "content": schema.StringAttribute{ - MarkdownDescription: "The content of the guardrail, written in Resourcely's Really language", + MarkdownDescription: "The guardrail policy written in the [Really policy language](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). Must specify exactly one of `content` or `guardrail_template_series_id`.", Optional: true, Computed: true, }, "guardrail_template_series_id": schema.StringAttribute{ - MarkdownDescription: "The series id of the guardrail template used to render the policies", + MarkdownDescription: "The series id of the guardrail template used to render the policy. Must specify exactly one of `guardrail_template_series_id` or `content`.", Optional: true, Computed: true, Default: stringdefault.StaticString(""), }, "guardrail_template_inputs": schema.StringAttribute{ CustomType: jsontypes.NormalizedType{}, - MarkdownDescription: "A JSON encoding of values for the guardrail template inputs.\n\nExample: `guardrail_template_inputs = jsonencode({inputOne = \"value one\"})`", + MarkdownDescription: "A JSON encoding of values for the guardrail template inputs. Required if `guardrail_template_series_id` is used. Example: `guardrail_template_inputs = jsonencode({inputOne = \"value one\"})`", Optional: true, }, }, diff --git a/templates/data-sources/guardrail.md.tmpl b/templates/data-sources/guardrail.md.tmpl new file mode 100644 index 0000000..be3ff70 --- /dev/null +++ b/templates/data-sources/guardrail.md.tmpl @@ -0,0 +1,16 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +{{ tffile .ExampleFile }} + +{{ .SchemaMarkdown | trimspace }} diff --git a/templates/resources/guardrail.md.tmpl b/templates/resources/guardrail.md.tmpl new file mode 100644 index 0000000..5fa6c9e --- /dev/null +++ b/templates/resources/guardrail.md.tmpl @@ -0,0 +1,31 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +Create a guardrail using the [Really policy langauge](https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails). + +{{ tffile .ExampleFile }} + +This resource also supports creating a guardrail from a Resourcely +Guardrail Template. Instead of specifying the `content`, specify the +`guardrail_template_series_id` and `guardrail_template_inputs` +instead. + +{{ tffile "examples/resources/resourcely_guardrail/resource_with_template.tf" }} + +{{ .SchemaMarkdown | trimspace }} + +## Import + +A guardrail can be imported using its series_id. + +{{codefile "shell" .ImportFile }} From 287524dd78c190dd128e7ada88a9c38a4847c5ca Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Mon, 25 Nov 2024 12:11:15 -0600 Subject: [PATCH 07/10] docs: add details to the context question resource and data source docs --- docs/data-sources/context_question.md | 54 +++++--- docs/resources/context_question.md | 121 +++++++++++++++--- .../data-source.tf | 3 + .../resourcely_context_question/import.sh | 1 + .../resourcely_context_question/resource.tf | 16 +++ .../resource_with_email_format.tf | 16 +++ .../resource_with_regex_format.tf | 17 +++ .../provider/context_question_data_source.go | 33 +++-- .../provider/context_question_resource.go | 41 +++--- .../data-sources/context_question.md.tmpl | 16 +++ templates/resources/context_question.md.tmpl | 33 +++++ 11 files changed, 282 insertions(+), 69 deletions(-) create mode 100644 examples/data-sources/resourcely_context_question/data-source.tf create mode 100644 examples/resources/resourcely_context_question/import.sh create mode 100644 examples/resources/resourcely_context_question/resource.tf create mode 100644 examples/resources/resourcely_context_question/resource_with_email_format.tf create mode 100644 examples/resources/resourcely_context_question/resource_with_regex_format.tf create mode 100644 templates/data-sources/context_question.md.tmpl create mode 100644 templates/resources/context_question.md.tmpl diff --git a/docs/data-sources/context_question.md b/docs/data-sources/context_question.md index 729d7bb..5a21a8b 100644 --- a/docs/data-sources/context_question.md +++ b/docs/data-sources/context_question.md @@ -1,42 +1,64 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_context_question Data Source - terraform-provider-resourcely" subcategory: "" description: |- - A resourcely ContextQuestion + A context question https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. + Soime examples include: + -What type of data will be stored in this infrastructure? + What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? + Three types of context questions are supported: + TextSingle ChoiceMultiple Choice --- # resourcely_context_question (Data Source) -A resourcely ContextQuestion +A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. +Soime examples include: +-What type of data will be stored in this infrastructure? +- What application is this infrastructure associated with? +- What is the email address the person/team responsible for this infrastructure? + +Three types of context questions are supported: + +- Text +- Single Choice +- Multiple Choice + +## Example Usage + +```terraform +data "resourcely_context_question" "example" { + series_id = "00000000-00000000-00000000-00000000" +} +``` ## Schema ### Required -- `series_id` (String) UUID for the global context +- `series_id` (String) UUID for the context question. ### Read-Only -- `answer_choices` (Attributes Set) (see [below for nested schema](#nestedatt--answer_choices)) -- `answer_format` (String) -- `blueprint_categories` (Set of String) Resource categories the context question applies to -- `excluded_blueprint_series` (Set of String) series_id for Blueprints exempt from this context question even though those blueprints belong to the context question's blueprint_categories -- `id` (String) UUID for this version. -- `label` (String) -- `priority` (Number) Priority of this question, relative to others. 0=high, 1=medium, 2=low -- `prompt` (String) -- `qtype` (String) -- `regex_pattern` (String) Regex validation for the acceptable answers to the context question +- `answer_choices` (Attributes Set) The answer choices from which the developer can select. Applicable only when `qtype` is `QTYPE_SINGLE_SELECT` or `QTYPE_MULTI_SELECT`. (see [below for nested schema](#nestedatt--answer_choices)) +- `answer_format` (String) A format validation for acceptable answers to the context question. Applicable only when `qtype` is `QTYPE_TEXT` . Will be one of `ANSWER_TEXT`, `ANSWER_NUMBER`, `ANSWER_EMAIL`, or `ANSWER_REGEX`. If `ANSWER_REGEX`, the `regex_pattern` property will also be set. +- `blueprint_categories` (Set of String) The blueprint categories to which this context question applies. This question will be asked whenever a developer uses a blueprint in these categories. +- `excluded_blueprint_series` (Set of String) The series_ids of blueprints for which this question should not be asked, even if those blueprints belong to the context question's blueprint_categories. +- `id` (String) UUID for the current version of this context question. +- `label` (String) A key used to reference the context question in blueprints and guardrails. Is unique within your Resourcley tenant. +- `priority` (Number) The priority of this question, relative to others. 0=high, 1=medium, 2=low +- `prompt` (String) The question that Resourcely will ask your developers. +- `qtype` (String) The type of the question. Will be one of `QYTPE_TEXT`, `QYTPE_SINGLE_SELECT`, or `QTYPE_MULTI_SELECT`. +- `regex_pattern` (String) A regex validation for the acceptable answers to the context question. Applicable only when both `qtype` is `QTYPE_TEXT` and `answer_format` is `ANSWER_REGEX`. - `scope` (String) -- `version` (Number) Specific version of the global context +- `version` (Number) Incrementing version number of the context question. ### Nested Schema for `answer_choices` Read-Only: -- `label` (String) +- `label` (String) The value for the answer choice. diff --git a/docs/resources/context_question.md b/docs/resources/context_question.md index c9c7fc3..bc9ed21 100644 --- a/docs/resources/context_question.md +++ b/docs/resources/context_question.md @@ -1,45 +1,134 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_context_question Resource - terraform-provider-resourcely" subcategory: "" description: |- - A Resourcely Context Question + A context question https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. + Soime examples include: + -What type of data will be stored in this infrastructure? + What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? + Three types of context questions are supported: + TextSingle ChoiceMultiple Choice --- # resourcely_context_question (Resource) -A Resourcely Context Question +A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. +Soime examples include: +-What type of data will be stored in this infrastructure? +- What application is this infrastructure associated with? +- What is the email address the person/team responsible for this infrastructure? + +Three types of context questions are supported: + +- Text +- Single Choice +- Multiple Choice + +## Example Usage + +Create a simple, multi-select context question. + +```terraform +resource "resourcely_context_question" "data_classification" { + label = "classification" + prompt = "What kind of data is stored by this infrastructure?" + + qtype = "QTYPE_MULTI_SELECT" + answer_choices = [ + { label = "financial" }, + { label = "pii" }, + { label = "proprietary" }, + { label = "public" }, + ] + + blueprint_categories = ["BLUEPRINT_BLOB_STORAGE", "BLUEPRINT_DATABASE"] + + priority = 1 +} +``` + + +Context questions with "text" type can restrict the allowed answer formats. For example, create a context question that asks for an email address. + +```terraform +resource "resourcely_context_question" "owner" { + label = "owner" + prompt = "What is the email address of the team or person responsible for this infrastructure?" + + qtype = "QTYPE_TEXT" + answer_format = "ANSWER_EMAIL" + + blueprint_categories = [ + "BLUEPRINT_COMPUTE", + "BLUEPRINT_DATABASE", + "BLUEPRINT_NETWORKING", + "BLUEPRINT_SERVERLESS_COMPUTE" + ] + + priority = 0 +} +``` + +Or, create a context question that asks for a project code comprising 6 hex digits. + +```terraform +resource "resourcely_context_question" "project_code" { + label = "project_code" + prompt = "What is the project code that this infrastructure should be associated with?" + + qtype = "QTYPE_TEXT" + answer_format = "ANSWER_REGEX" + regex_pattern = "^[A-Z0-9]{6}$" + + blueprint_categories = [ + "BLUEPRINT_COMPUTE", + "BLUEPRINT_DATABASE", + "BLUEPRINT_NETWORKING", + "BLUEPRINT_SERVERLESS_COMPUTE" + ] + + priority = 2 +} +``` ## Schema ### Required -- `label` (String) -- `prompt` (String) -- `qtype` (String) +- `label` (String) A key used to reference the context question in blueprints and guardrails. Must be unique within your Resourcley tenant. +- `prompt` (String) The question that Resourcely with ask your developers. +- `qtype` (String) The type of the question. Must be one of `QTYPE_TEXT`, `QTYPE_SINGLE_SELECT`, or `QTYPE_MULTI_SELECT` - `scope` (String) ### Optional -- `answer_choices` (Attributes Set) (see [below for nested schema](#nestedatt--answer_choices)) -- `answer_format` (String) -- `blueprint_categories` (Set of String) -- `excluded_blueprint_series` (Set of String) series_id for Blueprints exempt from this context question even though those blueprints belong to the context question's blueprint_categories -- `priority` (Number) Priority of this question, relative to others. 0=high, 1=medium, 2=low -- `regex_pattern` (String) Regex validation for the acceptable answers to the context question +- `answer_choices` (Attributes Set) The answer choices from which the developer can select. Applicable only when `qtype` is `QTYPE_SINGLE_SELECT` or `QTYPE_MULTI_SELECT`. (see [below for nested schema](#nestedatt--answer_choices)) +- `answer_format` (String) A format validation for acceptable answers to the context question. Applicable only when `qtype` is `QTYPE_TEXT` . Must be one of `ANSWER_TEXT`, `ANSWER_NUMBER`, `ANSWER_EMAIL`, or `ANSWER_REGEX`. If `ANSWER_REGEX`, must also specify the `regex_pattern` property. +- `blueprint_categories` (Set of String) The blueprint categories to which this context question applies. This question will be asked whenever a developer uses a blueprint in these categories. +- `excluded_blueprint_series` (Set of String) The series_ids of blueprints for which this question should not be asked, even if those blueprints belong to the context question's blueprint_categories. +- `priority` (Number) The priority of this question, relative to others. 0=high, 1=medium, 2=low +- `regex_pattern` (String) A regex validation for the acceptable answers to the context question. Applicable only when both `qtype` is `QTYPE_TEXT` and `answer_format` is `ANSWER_REGEX`. ### Read-Only -- `id` (String) UUID for this version. -- `series_id` (String) UUID for the Context Question -- `version` (Number) Specific version of the Global Context +- `id` (String) UUID for the current version of the context question. +- `series_id` (String) UUID for the context question. +- `version` (Number) Incrementing version number for the current version of this context question. ### Nested Schema for `answer_choices` Required: -- `label` (String) +- `label` (String) The value for the answer choice. + +## Import + +A blueprint can be imported using its series_id. + +```shell +terraform import resourcely_context_question.example 00000000-00000000-00000000-00000000 +``` diff --git a/examples/data-sources/resourcely_context_question/data-source.tf b/examples/data-sources/resourcely_context_question/data-source.tf new file mode 100644 index 0000000..8210473 --- /dev/null +++ b/examples/data-sources/resourcely_context_question/data-source.tf @@ -0,0 +1,3 @@ +data "resourcely_context_question" "example" { + series_id = "00000000-00000000-00000000-00000000" +} diff --git a/examples/resources/resourcely_context_question/import.sh b/examples/resources/resourcely_context_question/import.sh new file mode 100644 index 0000000..79ab84e --- /dev/null +++ b/examples/resources/resourcely_context_question/import.sh @@ -0,0 +1 @@ +terraform import resourcely_context_question.example 00000000-00000000-00000000-00000000 diff --git a/examples/resources/resourcely_context_question/resource.tf b/examples/resources/resourcely_context_question/resource.tf new file mode 100644 index 0000000..df56a29 --- /dev/null +++ b/examples/resources/resourcely_context_question/resource.tf @@ -0,0 +1,16 @@ +resource "resourcely_context_question" "data_classification" { + label = "classification" + prompt = "What kind of data is stored by this infrastructure?" + + qtype = "QTYPE_MULTI_SELECT" + answer_choices = [ + { label = "financial" }, + { label = "pii" }, + { label = "proprietary" }, + { label = "public" }, + ] + + blueprint_categories = ["BLUEPRINT_BLOB_STORAGE", "BLUEPRINT_DATABASE"] + + priority = 1 +} diff --git a/examples/resources/resourcely_context_question/resource_with_email_format.tf b/examples/resources/resourcely_context_question/resource_with_email_format.tf new file mode 100644 index 0000000..a77bafc --- /dev/null +++ b/examples/resources/resourcely_context_question/resource_with_email_format.tf @@ -0,0 +1,16 @@ +resource "resourcely_context_question" "owner" { + label = "owner" + prompt = "What is the email address of the team or person responsible for this infrastructure?" + + qtype = "QTYPE_TEXT" + answer_format = "ANSWER_EMAIL" + + blueprint_categories = [ + "BLUEPRINT_COMPUTE", + "BLUEPRINT_DATABASE", + "BLUEPRINT_NETWORKING", + "BLUEPRINT_SERVERLESS_COMPUTE" + ] + + priority = 0 +} diff --git a/examples/resources/resourcely_context_question/resource_with_regex_format.tf b/examples/resources/resourcely_context_question/resource_with_regex_format.tf new file mode 100644 index 0000000..defd2b9 --- /dev/null +++ b/examples/resources/resourcely_context_question/resource_with_regex_format.tf @@ -0,0 +1,17 @@ +resource "resourcely_context_question" "project_code" { + label = "project_code" + prompt = "What is the project code that this infrastructure should be associated with?" + + qtype = "QTYPE_TEXT" + answer_format = "ANSWER_REGEX" + regex_pattern = "^[A-Z0-9]{6}$" + + blueprint_categories = [ + "BLUEPRINT_COMPUTE", + "BLUEPRINT_DATABASE", + "BLUEPRINT_NETWORKING", + "BLUEPRINT_SERVERLESS_COMPUTE" + ] + + priority = 2 +} diff --git a/internal/provider/context_question_data_source.go b/internal/provider/context_question_data_source.go index a2dd2e6..5a43ecb 100644 --- a/internal/provider/context_question_data_source.go +++ b/internal/provider/context_question_data_source.go @@ -30,20 +30,18 @@ func (d *ContextQuestionDataSource) Metadata(_ context.Context, req datasource.M func (d *ContextQuestionDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A resourcely ContextQuestion", - + MarkdownDescription: "A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource.\n\nSoime examples include:\n\n-What type of data will be stored in this infrastructure?\n- What application is this infrastructure associated with?\n- What is the email address the person/team responsible for this infrastructure?\n\nThree types of context questions are supported:\n\n- Text\n- Single Choice\n- Multiple Choice\n", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of this context question.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the global context", + MarkdownDescription: "UUID for the context question.", Required: true, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the global context", + MarkdownDescription: "Incrementing version number of the context question.", Computed: true, }, "scope": schema.StringAttribute{ @@ -51,49 +49,50 @@ func (d *ContextQuestionDataSource) Schema(_ context.Context, _ datasource.Schem Computed: true, }, "label": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "A key used to reference the context question in blueprints and guardrails. Is unique within your Resourcley tenant.", Computed: true, }, "prompt": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The question that Resourcely will ask your developers.", Computed: true, }, "qtype": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The type of the question. Will be one of `QYTPE_TEXT`, `QYTPE_SINGLE_SELECT`, or `QTYPE_MULTI_SELECT`.", Computed: true, }, "answer_format": schema.StringAttribute{ - MarkdownDescription: "", - Computed: true, + MarkdownDescription: "A format validation for acceptable answers to the context question. Applicable only when `qtype` is `QTYPE_TEXT` . Will be one of `ANSWER_TEXT`, `ANSWER_NUMBER`, `ANSWER_EMAIL`, or `ANSWER_REGEX`. If `ANSWER_REGEX`, the `regex_pattern` property will also be set.", + + Computed: true, }, "answer_choices": schema.SetNestedAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The answer choices from which the developer can select. Applicable only when `qtype` is `QTYPE_SINGLE_SELECT` or `QTYPE_MULTI_SELECT`.", Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ "label": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The value for the answer choice.", Computed: true, }, }, }, }, "blueprint_categories": schema.SetAttribute{ + MarkdownDescription: "The blueprint categories to which this context question applies. This question will be asked whenever a developer uses a blueprint in these categories.", ElementType: basetypes.StringType{}, Computed: true, - MarkdownDescription: "Resource categories the context question applies to", }, "regex_pattern": schema.StringAttribute{ - MarkdownDescription: "Regex validation for the acceptable answers to the context question", + MarkdownDescription: "A regex validation for the acceptable answers to the context question. Applicable only when both `qtype` is `QTYPE_TEXT` and `answer_format` is `ANSWER_REGEX`.", Computed: true, }, "excluded_blueprint_series": schema.SetAttribute{ + MarkdownDescription: "The series_ids of blueprints for which this question should not be asked, even if those blueprints belong to the context question's blueprint_categories.", ElementType: basetypes.StringType{}, Computed: true, - MarkdownDescription: "series_id for Blueprints exempt from this context question even though those blueprints belong to the context question's blueprint_categories", }, "priority": schema.Int64Attribute{ - MarkdownDescription: "Priority of this question, relative to others. 0=high, 1=medium, 2=low", + MarkdownDescription: "The priority of this question, relative to others. 0=high, 1=medium, 2=low", Computed: true, }, }, diff --git a/internal/provider/context_question_resource.go b/internal/provider/context_question_resource.go index 64ed0a4..9c42d31 100644 --- a/internal/provider/context_question_resource.go +++ b/internal/provider/context_question_resource.go @@ -46,23 +46,21 @@ func (r *ContextQuestionResource) Metadata(_ context.Context, req resource.Metad func (r *ContextQuestionResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A Resourcely Context Question", - + MarkdownDescription: "A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource.\n\nSoime examples include:\n\n-What type of data will be stored in this infrastructure?\n- What application is this infrastructure associated with?\n- What is the email address the person/team responsible for this infrastructure?\n\nThree types of context questions are supported:\n\n- Text\n- Single Choice\n- Multiple Choice\n", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of the context question.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the Context Question", + MarkdownDescription: "UUID for the context question.", Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the Global Context", + MarkdownDescription: "Incrementing version number for the current version of this context question.", Computed: true, }, "scope": schema.StringAttribute{ @@ -73,15 +71,15 @@ func (r *ContextQuestionResource) Schema(_ context.Context, _ resource.SchemaReq }, }, "label": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "A key used to reference the context question in blueprints and guardrails. Must be unique within your Resourcley tenant.", Required: true, }, "prompt": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The question that Resourcely with ask your developers.", Required: true, }, "qtype": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The type of the question. Must be one of `QTYPE_TEXT`, `QTYPE_SINGLE_SELECT`, or `QTYPE_MULTI_SELECT`", Required: true, Validators: []validator.String{ stringvalidator.OneOf( @@ -91,7 +89,7 @@ func (r *ContextQuestionResource) Schema(_ context.Context, _ resource.SchemaReq }, }, "answer_format": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "A format validation for acceptable answers to the context question. Applicable only when `qtype` is `QTYPE_TEXT` . Must be one of `ANSWER_TEXT`, `ANSWER_NUMBER`, `ANSWER_EMAIL`, or `ANSWER_REGEX`. If `ANSWER_REGEX`, must also specify the `regex_pattern` property.", Default: stringdefault.StaticString("ANSWER_TEXT"), Optional: true, Computed: true, @@ -105,14 +103,14 @@ func (r *ContextQuestionResource) Schema(_ context.Context, _ resource.SchemaReq }, }, "answer_choices": schema.SetNestedAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The answer choices from which the developer can select. Applicable only when `qtype` is `QTYPE_SINGLE_SELECT` or `QTYPE_MULTI_SELECT`.", Default: setdefault.StaticValue(types.SetValueMust(types.ObjectType{AttrTypes: map[string]attr.Type{"label": types.StringType}}, nil)), Optional: true, Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ "label": schema.StringAttribute{ - MarkdownDescription: "", + MarkdownDescription: "The value for the answer choice.", Required: true, }, }, @@ -120,41 +118,44 @@ func (r *ContextQuestionResource) Schema(_ context.Context, _ resource.SchemaReq }, "blueprint_categories": schema.SetAttribute{ ElementType: basetypes.StringType{}, - MarkdownDescription: "", + MarkdownDescription: "The blueprint categories to which this context question applies. This question will be asked whenever a developer uses a blueprint in these categories.", Default: setdefault.StaticValue(types.SetValueMust(types.StringType, nil)), Computed: true, Optional: true, Validators: []validator.Set{ // All list items must pass the nested validators setvalidator.ValueStringsAre(stringvalidator.OneOf( + "BLUEPRINT_ASYNC_PROCESSING", "BLUEPRINT_BLOB_STORAGE", - "BLUEPRINT_NETWORKING", - "BLUEPRINT_DATABASE", "BLUEPRINT_COMPUTE", - "BLUEPRINT_SERVERLESS_COMPUTE", - "BLUEPRINT_ASYNC_PROCESSING", "BLUEPRINT_CONTAINERIZATION", + "BLUEPRINT_DATABASE", + "BLUEPRINT_GITHUB_REPO", + "BLUEPRINT_GITHUB_REPO_TEAM", + "BLUEPRINT_IAM", "BLUEPRINT_LOGS_AND_METRICS", + "BLUEPRINT_NETWORKING", + "BLUEPRINT_SERVERLESS_COMPUTE", ), ), }, }, "regex_pattern": schema.StringAttribute{ + MarkdownDescription: "A regex validation for the acceptable answers to the context question. Applicable only when both `qtype` is `QTYPE_TEXT` and `answer_format` is `ANSWER_REGEX`.", Default: stringdefault.StaticString(""), - MarkdownDescription: "Regex validation for the acceptable answers to the context question", Optional: true, Computed: true, }, "excluded_blueprint_series": schema.SetAttribute{ + MarkdownDescription: "The series_ids of blueprints for which this question should not be asked, even if those blueprints belong to the context question's blueprint_categories.", Default: setdefault.StaticValue(types.SetValueMust(types.StringType, nil)), ElementType: basetypes.StringType{}, - MarkdownDescription: "series_id for Blueprints exempt from this context question even though those blueprints belong to the context question's blueprint_categories", Optional: true, Computed: true, }, "priority": schema.Int64Attribute{ + MarkdownDescription: "The priority of this question, relative to others. 0=high, 1=medium, 2=low", Default: int64default.StaticInt64(0), - MarkdownDescription: "Priority of this question, relative to others. 0=high, 1=medium, 2=low", Optional: true, Computed: true, Validators: []validator.Int64{ diff --git a/templates/data-sources/context_question.md.tmpl b/templates/data-sources/context_question.md.tmpl new file mode 100644 index 0000000..be3ff70 --- /dev/null +++ b/templates/data-sources/context_question.md.tmpl @@ -0,0 +1,16 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +{{ tffile .ExampleFile }} + +{{ .SchemaMarkdown | trimspace }} diff --git a/templates/resources/context_question.md.tmpl b/templates/resources/context_question.md.tmpl new file mode 100644 index 0000000..bfa42c4 --- /dev/null +++ b/templates/resources/context_question.md.tmpl @@ -0,0 +1,33 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +Create a simple, multi-select context question. + +{{ tffile .ExampleFile }} + + +Context questions with "text" type can restrict the allowed answer formats. For example, create a context question that asks for an email address. + +{{ tffile "examples/resources/resourcely_context_question/resource_with_email_format.tf" }} + +Or, create a context question that asks for a project code comprising 6 hex digits. + +{{ tffile "examples/resources/resourcely_context_question/resource_with_regex_format.tf" }} + +{{ .SchemaMarkdown | trimspace }} + +## Import + +A blueprint can be imported using its series_id. + +{{codefile "shell" .ImportFile }} From 7aec66b609ee0fe3efcbe5b190b1cf7400d9b0cb Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Mon, 25 Nov 2024 14:55:36 -0600 Subject: [PATCH 08/10] docs: add details to the global value resource and data source docs --- docs/data-sources/global_value.md | 41 ++--- docs/resources/global_value.md | 171 +++++++++++++++--- .../resourcely_global_value/data-source.tf | 3 + .../resourcely_global_value/import.sh | 1 + .../resourcely_global_value/resource.tf | 29 +++ .../resource_with_object_values.tf | 81 +++++++++ internal/provider/global_value_data_source.go | 28 ++- internal/provider/global_value_resource.go | 28 ++- templates/data-sources/global_value.md.tmpl | 16 ++ templates/resources/global_value.md.tmpl | 31 ++++ 10 files changed, 355 insertions(+), 74 deletions(-) create mode 100644 examples/data-sources/resourcely_global_value/data-source.tf create mode 100644 examples/resources/resourcely_global_value/import.sh create mode 100644 examples/resources/resourcely_global_value/resource.tf create mode 100644 examples/resources/resourcely_global_value/resource_with_object_values.tf create mode 100644 templates/data-sources/global_value.md.tmpl create mode 100644 templates/resources/global_value.md.tmpl diff --git a/docs/data-sources/global_value.md b/docs/data-sources/global_value.md index 5742aba..429dffa 100644 --- a/docs/data-sources/global_value.md +++ b/docs/data-sources/global_value.md @@ -1,49 +1,48 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_global_value Data Source - terraform-provider-resourcely" subcategory: "" description: |- - A Resourcely global value + A global value https://docs.resourcely.io/concepts/other-features-and-settings/global-values allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc. --- # resourcely_global_value (Data Source) -A Resourcely global value +A [global value](https://docs.resourcely.io/concepts/other-features-and-settings/global-values) allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc. +## Example Usage +```terraform +data "resourcely_global_value" "example" { + series_id = "00000000-00000000-00000000-00000000" +} +``` ## Schema ### Required -- `series_id` (String) UUID for the global value +- `series_id` (String) UUID for the global value. ### Read-Only -- `description` (String) A longer description -- `id` (String) UUID for this version. -- `is_deprecated` (Boolean) True if the global value should not be used in new blueprints or guardrails +- `description` (String) A description of the purpose of the global value. +- `id` (String) UUID for the current version of the global value. +- `is_deprecated` (Boolean) Set to true if the global value should not be used in new blueprints or guardrails - `key` (String) An immutable identifier used to reference this global value in blueprints or guardrails. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. -- `name` (String) A short display name -- `options` (Attributes List) The list of value options for this global value (see [below for nested schema](#nestedatt--options)) -- `type` (String) The type of options in the global value. Can be one of `PRESET_VALUE_TEXT`, `PRESET_VALUE_NUMBER`, `PRESET_VALUE_LIST`, `PRESET_VALUE_OBJECT` -- `version` (Number) Specific version of the global value +- `name` (String) The name of the global value. +- `options` (Attributes List) The list of value options for this global value. (see [below for nested schema](#nestedatt--options)) +- `type` (String) The type of options in the global value. Will be one of `PRESET_VALUE_TEXT`, `PRESET_VALUE_NUMBER`, `PRESET_VALUE_LIST`, `PRESET_VALUE_OBJECT` +- `version` (Number) Incrementing version number for the current version of the global value. ### Nested Schema for `options` Read-Only: -- `description` (String) A longer description -- `key` (String) An immutable identifier for ths option. - -Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. -- `label` (String) A unique short display name -- `value` (String) A JSON encoding of the option's value. This value must match the declared type of the global value. - -Example: `value = jsonencode("a")` - -Example: `value = jsonencode(["a", "b"])` +- `description` (String) A description of this option's meaning. +- `key` (String) An immutable identifier for ths option. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. +- `label` (String) A unique display name +- `value` (String) A JSON encoding of the option's value.` diff --git a/docs/resources/global_value.md b/docs/resources/global_value.md index e59e365..bdec65f 100644 --- a/docs/resources/global_value.md +++ b/docs/resources/global_value.md @@ -1,55 +1,180 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "resourcely_global_value Resource - terraform-provider-resourcely" subcategory: "" description: |- - A Resourcely GlobalValue + A global value https://docs.resourcely.io/concepts/other-features-and-settings/global-values allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc. + This global value API does not support deletion. Deleting the Terraform resource will remove the resource from the Terraform state file, but will not actually delete the global value entity. Set is_deprecated = true to tell Resourcely that this global value should no longer be used by new blueprints or guardrails. --- # resourcely_global_value (Resource) -A Resourcely GlobalValue - - +A [global value](https://docs.resourcely.io/concepts/other-features-and-settings/global-values) allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc. + +This global value API does not support deletion. Deleting the Terraform resource will remove the resource from the Terraform state file, but will not actually delete the global value entity. Set `is_deprecated = true` to tell Resourcely that this global value should no longer be used by new blueprints or guardrails. + +## Example Usage + +Create a global value containing all the departments within the company. + +```terraform +resource "resourcely_global_value" "departments" { + name = "Departments" + key = "departments" + description = "All departments within MyCompany" + + type = "PRESET_VALUE_TEXT" + options = [ + { + key = "product", + label = "Product", + value = "product", + }, + { + key = "it", + label = "IT", + value = "IT", + }, + { + key = "marketing", + label = "Marketing", + value = "market", + }, + { + key = "engingeering", + label = "Engineering", + value = "eng", + }, + ] +} +``` + +Create a global value listing the AMI attributes for three Linux +distributions. Then create a blueprint that creates an instance, +querying for the AMI using the attributes of the selected +distribution. + +```terraform +resource "resourcely_global_value" "amis" { + name = "EC2 AMI" + key = "amis" + description = "AMI selectors." + + type = "PRESET_VALUE_OBJECT" + options = [ + { + key = "ubuntu", + label = "Ubuntu", + value = { + name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*", + virt_type = "hvm", + owner = "099720109477", + } + }, + { + key = "centos", + label = "CentOS", + value = { + name = "CentOS Stream 9 x84_64 *", + virt_type = "hvm", + owner = "125523088429", + }, + }, + { + key = "debian", + label = "Debian", + value = { + name = "debian-12-amd64-*", + virt_type = "hvm", + owner = "136693071363", + }, + }, + ] +} + +resource "resourcely_blueprint" "simple_instance" { + name = "A simple EC2 Instance" + description = "Creates a simple EC2 instance using one of three preselected AMIs." + + cloud_provider = "PROVIDER_AMAZON" + categories = ["BLUEPRINT_COMPUTE"] + + is_published = true + + content = <<-EOT + --- + constants: + __name: "{{ bucket }}_{{ __guid }}" + variables: + ami: + description: The Linux distribution to run on this instance. + global_value: amis + --- + data "aws_ami" "{{ __name }}" { + most_recent = true + + filter { + name = "name" + values = [{{ ami.name }}] + } + + filter { + name = "virtualization-type" + values = [{{ ami.virt_type }}] + } + + owners = [{{ ami.owner }}] + } + + resource "aws_instance" "{{ __name }}" { + ami = data.aws_ami.{{ __name }}.id + instance_type = "t3.micro" + + tags = { + Name = "HelloWorld" + } + } + EOT +} +``` ## Schema ### Required -- `key` (String) An immutable identifier used to reference this global value in blueprints or guardrails. - -Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. -- `name` (String) A short display name -- `options` (Attributes List) The list of value options for this global value (see [below for nested schema](#nestedatt--options)) +- `key` (String) An immutable identifier used to reference this global value in blueprints or guardrails. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. +- `name` (String) The name of the global value. +- `options` (Attributes List) The list of value options for this global value. (see [below for nested schema](#nestedatt--options)) - `type` (String) The type of options in the global value. Can be one of `PRESET_VALUE_TEXT`, `PRESET_VALUE_NUMBER`, `PRESET_VALUE_LIST`, `PRESET_VALUE_OBJECT` ### Optional -- `description` (String) A longer description -- `is_deprecated` (Boolean) True if the global value should not be used in new blueprints or guardrails +- `description` (String) A description of the purpose of the global value. +- `is_deprecated` (Boolean) Set to true if the global value should not be used in new blueprints or guardrails. ### Read-Only -- `id` (String) UUID for this version of the global value -- `series_id` (String) UUID for the global value -- `version` (Number) Version of the global value +- `id` (String) UUID for the current version of the global value. +- `series_id` (String) UUID for the global value. +- `version` (Number) Incrementing version number for the current version of the global value. ### Nested Schema for `options` Required: -- `key` (String) An immutable identifier for ths option. +- `key` (String) An immutable identifier for ths option. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. +- `label` (String) A unique display name. +- `value` (String) A JSON encoding of the option's value. This value must match the declared type of the global value. Example: `value = jsonencode("a")` Example: `value = jsonencode(["a", "b"])` -Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`. -- `label` (String) A unique short display name -- `value` (String) A JSON encoding of the option's value. This value must match the declared type of the global value. +Optional: -Example: `value = jsonencode("a")` +- `description` (String) A description of this option's meaning. -Example: `value = jsonencode(["a", "b"])` +## Import -Optional: +A global value can be imported using its series_id. -- `description` (String) A longer description +```shell +terraform import resourcely_global_value.example 00000000-00000000-00000000-00000000 +``` diff --git a/examples/data-sources/resourcely_global_value/data-source.tf b/examples/data-sources/resourcely_global_value/data-source.tf new file mode 100644 index 0000000..7119bac --- /dev/null +++ b/examples/data-sources/resourcely_global_value/data-source.tf @@ -0,0 +1,3 @@ +data "resourcely_global_value" "example" { + series_id = "00000000-00000000-00000000-00000000" +} diff --git a/examples/resources/resourcely_global_value/import.sh b/examples/resources/resourcely_global_value/import.sh new file mode 100644 index 0000000..cdd0fc9 --- /dev/null +++ b/examples/resources/resourcely_global_value/import.sh @@ -0,0 +1 @@ +terraform import resourcely_global_value.example 00000000-00000000-00000000-00000000 diff --git a/examples/resources/resourcely_global_value/resource.tf b/examples/resources/resourcely_global_value/resource.tf new file mode 100644 index 0000000..f2e722f --- /dev/null +++ b/examples/resources/resourcely_global_value/resource.tf @@ -0,0 +1,29 @@ +resource "resourcely_global_value" "departments" { + name = "Departments" + key = "departments" + description = "All departments within MyCompany" + + type = "PRESET_VALUE_TEXT" + options = [ + { + key = "product", + label = "Product", + value = "product", + }, + { + key = "it", + label = "IT", + value = "IT", + }, + { + key = "marketing", + label = "Marketing", + value = "market", + }, + { + key = "engingeering", + label = "Engineering", + value = "eng", + }, + ] +} diff --git a/examples/resources/resourcely_global_value/resource_with_object_values.tf b/examples/resources/resourcely_global_value/resource_with_object_values.tf new file mode 100644 index 0000000..fcff589 --- /dev/null +++ b/examples/resources/resourcely_global_value/resource_with_object_values.tf @@ -0,0 +1,81 @@ +resource "resourcely_global_value" "amis" { + name = "EC2 AMI" + key = "amis" + description = "AMI selectors." + + type = "PRESET_VALUE_OBJECT" + options = [ + { + key = "ubuntu", + label = "Ubuntu", + value = { + name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*", + virt_type = "hvm", + owner = "099720109477", + } + }, + { + key = "centos", + label = "CentOS", + value = { + name = "CentOS Stream 9 x84_64 *", + virt_type = "hvm", + owner = "125523088429", + }, + }, + { + key = "debian", + label = "Debian", + value = { + name = "debian-12-amd64-*", + virt_type = "hvm", + owner = "136693071363", + }, + }, + ] +} + +resource "resourcely_blueprint" "simple_instance" { + name = "A simple EC2 Instance" + description = "Creates a simple EC2 instance using one of three preselected AMIs." + + cloud_provider = "PROVIDER_AMAZON" + categories = ["BLUEPRINT_COMPUTE"] + + is_published = true + + content = <<-EOT + --- + constants: + __name: "{{ bucket }}_{{ __guid }}" + variables: + ami: + description: The Linux distribution to run on this instance. + global_value: amis + --- + data "aws_ami" "{{ __name }}" { + most_recent = true + + filter { + name = "name" + values = [{{ ami.name }}] + } + + filter { + name = "virtualization-type" + values = [{{ ami.virt_type }}] + } + + owners = [{{ ami.owner }}] + } + + resource "aws_instance" "{{ __name }}" { + ami = data.aws_ami.{{ __name }}.id + instance_type = "t3.micro" + + tags = { + Name = "HelloWorld" + } + } + EOT +} diff --git a/internal/provider/global_value_data_source.go b/internal/provider/global_value_data_source.go index c45d9d6..07ffbed 100644 --- a/internal/provider/global_value_data_source.go +++ b/internal/provider/global_value_data_source.go @@ -29,24 +29,22 @@ func (d *GlobalValueDataSource) Metadata(_ context.Context, req datasource.Metad func (d *GlobalValueDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A Resourcely global value", - + MarkdownDescription: "A [global value](https://docs.resourcely.io/concepts/other-features-and-settings/global-values) allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version.", + MarkdownDescription: "UUID for the current version of the global value.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the global value", + MarkdownDescription: "UUID for the global value.", Required: true, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Specific version of the global value", + MarkdownDescription: "Incrementing version number for the current version of the global value.", Computed: true, }, "is_deprecated": schema.BoolAttribute{ - MarkdownDescription: "True if the global value should not be used in new blueprints or guardrails", + MarkdownDescription: "Set to true if the global value should not be used in new blueprints or guardrails", Computed: true, }, "key": schema.StringAttribute{ @@ -54,40 +52,40 @@ func (d *GlobalValueDataSource) Schema(_ context.Context, _ datasource.SchemaReq Computed: true, }, "name": schema.StringAttribute{ - MarkdownDescription: "A short display name", + MarkdownDescription: "The name of the global value.", Computed: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "A longer description", + MarkdownDescription: "A description of the purpose of the global value.", Computed: true, }, "type": schema.StringAttribute{ - MarkdownDescription: "The type of options in the global value. Can be one of `PRESET_VALUE_TEXT`, `PRESET_VALUE_NUMBER`, `PRESET_VALUE_LIST`, `PRESET_VALUE_OBJECT`", + MarkdownDescription: "The type of options in the global value. Will be one of `PRESET_VALUE_TEXT`, `PRESET_VALUE_NUMBER`, `PRESET_VALUE_LIST`, `PRESET_VALUE_OBJECT`", Computed: true, }, "options": schema.ListNestedAttribute{ NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ "key": schema.StringAttribute{ - MarkdownDescription: "An immutable identifier for ths option.\n\nMust start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`.", + MarkdownDescription: "An immutable identifier for ths option. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`.", Computed: true, }, "label": schema.StringAttribute{ - MarkdownDescription: "A unique short display name", + MarkdownDescription: "A unique display name", Computed: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "A longer description", + MarkdownDescription: "A description of this option's meaning.", Computed: true, }, "value": schema.StringAttribute{ CustomType: jsontypes.NormalizedType{}, - MarkdownDescription: "A JSON encoding of the option's value. This value must match the declared type of the global value.\n\nExample: `value = jsonencode(\"a\")`\n\nExample: `value = jsonencode([\"a\", \"b\"])`", + MarkdownDescription: "A JSON encoding of the option's value.`", Computed: true, }, }, }, - MarkdownDescription: "The list of value options for this global value", + MarkdownDescription: "The list of value options for this global value.", Computed: true, }, }, diff --git a/internal/provider/global_value_resource.go b/internal/provider/global_value_resource.go index 69f80f5..9821f2a 100644 --- a/internal/provider/global_value_resource.go +++ b/internal/provider/global_value_resource.go @@ -51,44 +51,42 @@ func (r *GlobalValueResource) Schema( resp *resource.SchemaResponse, ) { resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "A Resourcely GlobalValue", - + MarkdownDescription: "A [global value](https://docs.resourcely.io/concepts/other-features-and-settings/global-values) allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc.\n\nThis global value API does not support deletion. Deleting the Terraform resource will remove the resource from the Terraform state file, but will not actually delete the global value entity. Set `is_deprecated = true` to tell Resourcely that this global value should no longer be used by new blueprints or guardrails.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - MarkdownDescription: "UUID for this version of the global value", + MarkdownDescription: "UUID for the current version of the global value.", Computed: true, }, "series_id": schema.StringAttribute{ - MarkdownDescription: "UUID for the global value", + MarkdownDescription: "UUID for the global value.", Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, }, "version": schema.Int64Attribute{ - MarkdownDescription: "Version of the global value", + MarkdownDescription: "Incrementing version number for the current version of the global value.", Computed: true, }, "is_deprecated": schema.BoolAttribute{ - MarkdownDescription: "True if the global value should not be used in new blueprints or guardrails", + MarkdownDescription: "Set to true if the global value should not be used in new blueprints or guardrails.", Default: booldefault.StaticBool(false), Computed: true, Optional: true, }, "key": schema.StringAttribute{ - MarkdownDescription: "An immutable identifier used to reference this global value in blueprints or guardrails.\n\nMust start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`.", + MarkdownDescription: "An immutable identifier used to reference this global value in blueprints or guardrails. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`.", Required: true, Validators: []validator.String{ stringvalidator.RegexMatches(regexp.MustCompile("^[a-z][a-z0-9_]*$"), "Key must start with a lowercase letter in`a-z` and include only characters in `a-z0-9_`."), }, }, "name": schema.StringAttribute{ - MarkdownDescription: "A short display name", + MarkdownDescription: "The name of the global value.", Required: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "A longer description", + MarkdownDescription: "A description of the purpose of the global value.", Default: stringdefault.StaticString(""), Computed: true, Optional: true, @@ -109,29 +107,29 @@ func (r *GlobalValueResource) Schema( NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ "key": schema.StringAttribute{ - MarkdownDescription: "An immutable identifier for ths option.\n\nMust start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`.", + MarkdownDescription: "An immutable identifier for ths option. Must start with a lowercase letter in `a-z` and include only characters in `a-z0-9_`.", Required: true, Validators: []validator.String{ stringvalidator.RegexMatches(regexp.MustCompile("^[a-z][a-z0-9_]*$"), "Key must start with a lowercase letter in`a-z` and include only characters in `a-z0-9_`."), }}, "label": schema.StringAttribute{ - MarkdownDescription: "A unique short display name", + MarkdownDescription: "A unique display name.", Required: true, }, "description": schema.StringAttribute{ - MarkdownDescription: "A longer description", + MarkdownDescription: "A description of this option's meaning.", Default: stringdefault.StaticString(""), Computed: true, Optional: true, }, "value": schema.StringAttribute{ CustomType: jsontypes.NormalizedType{}, - MarkdownDescription: "A JSON encoding of the option's value. This value must match the declared type of the global value.\n\nExample: `value = jsonencode(\"a\")`\n\nExample: `value = jsonencode([\"a\", \"b\"])`", + MarkdownDescription: "A JSON encoding of the option's value. This value must match the declared type of the global value. Example: `value = jsonencode(\"a\")` Example: `value = jsonencode([\"a\", \"b\"])`", Required: true, }, }, }, - MarkdownDescription: "The list of value options for this global value", + MarkdownDescription: "The list of value options for this global value.", Required: true, Validators: []validator.List{ listvalidator.SizeAtLeast(1), diff --git a/templates/data-sources/global_value.md.tmpl b/templates/data-sources/global_value.md.tmpl new file mode 100644 index 0000000..be3ff70 --- /dev/null +++ b/templates/data-sources/global_value.md.tmpl @@ -0,0 +1,16 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +{{ tffile .ExampleFile }} + +{{ .SchemaMarkdown | trimspace }} diff --git a/templates/resources/global_value.md.tmpl b/templates/resources/global_value.md.tmpl new file mode 100644 index 0000000..635b6ef --- /dev/null +++ b/templates/resources/global_value.md.tmpl @@ -0,0 +1,31 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +Create a global value containing all the departments within the company. + +{{ tffile .ExampleFile }} + +Create a global value listing the AMI attributes for three Linux +distributions. Then create a blueprint that creates an instance, +querying for the AMI using the attributes of the selected +distribution. + +{{ tffile "examples/resources/resourcely_global_value/resource_with_object_values.tf" }} + +{{ .SchemaMarkdown | trimspace }} + +## Import + +A global value can be imported using its series_id. + +{{codefile "shell" .ImportFile }} From da5102b10f589edc02ecb39d22b4d99fcee63c4c Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Mon, 25 Nov 2024 16:17:55 -0600 Subject: [PATCH 09/10] docs: fix typos --- docs/data-sources/blueprint.md | 4 ++-- docs/data-sources/context_question.md | 9 ++++----- docs/resources/blueprint.md | 4 ++-- docs/resources/context_question.md | 9 ++++----- internal/provider/blueprint_data_source.go | 2 +- internal/provider/blueprint_resource.go | 2 +- internal/provider/context_question_data_source.go | 2 +- internal/provider/context_question_resource.go | 2 +- 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/docs/data-sources/blueprint.md b/docs/data-sources/blueprint.md index cd1c915..c30a4c9 100644 --- a/docs/data-sources/blueprint.md +++ b/docs/data-sources/blueprint.md @@ -4,7 +4,7 @@ subcategory: "" description: |- A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: Define which options are available for properties of your resource(s).Apply gaurdrails to your resource(s) to prevent misconfiguration.Define what information to collect from your developers before provisioning the resource. - One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. + Once a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. The template is specified using Resourcely's TFT templating language. See the Authoring Your Own Blueprints https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints docs for details about TFT. The Resourcely Foundry https://portal.resourcely.io/foundry?mode=blueprint provides an IDE to assist with authoring the template. --- @@ -16,7 +16,7 @@ A blueprint is a configuration template used to provision cloud infrastructure r - Apply gaurdrails to your resource(s) to prevent misconfiguration. - Define what information to collect from your developers before provisioning the resource. -One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. +Once a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. The template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template. diff --git a/docs/data-sources/context_question.md b/docs/data-sources/context_question.md index 5a21a8b..522d852 100644 --- a/docs/data-sources/context_question.md +++ b/docs/data-sources/context_question.md @@ -3,9 +3,8 @@ page_title: "resourcely_context_question Data Source - terraform-provider-resour subcategory: "" description: |- A context question https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. - Soime examples include: - -What type of data will be stored in this infrastructure? - What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? + Some examples include: + What type of data will be stored in this infrastructure?What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? Three types of context questions are supported: TextSingle ChoiceMultiple Choice --- @@ -14,9 +13,9 @@ description: |- A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. -Soime examples include: +Some examples include: --What type of data will be stored in this infrastructure? +- What type of data will be stored in this infrastructure? - What application is this infrastructure associated with? - What is the email address the person/team responsible for this infrastructure? diff --git a/docs/resources/blueprint.md b/docs/resources/blueprint.md index b46d415..cd75f26 100644 --- a/docs/resources/blueprint.md +++ b/docs/resources/blueprint.md @@ -4,7 +4,7 @@ subcategory: "" description: |- A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: Define which options are available for properties of your resource(s).Apply gaurdrails to your resource(s) to prevent misconfiguration.Define what information to collect from your developers before provisioning the resource. - One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. + Once a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. The template is specified using Resourcely's TFT templating language. See the Authoring Your Own Blueprints https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints docs for details about TFT. The Resourcely Foundry https://portal.resourcely.io/foundry?mode=blueprint provides an IDE to assist with authoring the template. --- @@ -16,7 +16,7 @@ A blueprint is a configuration template used to provision cloud infrastructure r - Apply gaurdrails to your resource(s) to prevent misconfiguration. - Define what information to collect from your developers before provisioning the resource. -One a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. +Once a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. The template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template. diff --git a/docs/resources/context_question.md b/docs/resources/context_question.md index bc9ed21..7c3f886 100644 --- a/docs/resources/context_question.md +++ b/docs/resources/context_question.md @@ -3,9 +3,8 @@ page_title: "resourcely_context_question Resource - terraform-provider-resourcel subcategory: "" description: |- A context question https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. - Soime examples include: - -What type of data will be stored in this infrastructure? - What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? + Some examples include: + What type of data will be stored in this infrastructure?What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? Three types of context questions are supported: TextSingle ChoiceMultiple Choice --- @@ -14,9 +13,9 @@ description: |- A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. -Soime examples include: +Some examples include: --What type of data will be stored in this infrastructure? +- What type of data will be stored in this infrastructure? - What application is this infrastructure associated with? - What is the email address the person/team responsible for this infrastructure? diff --git a/internal/provider/blueprint_data_source.go b/internal/provider/blueprint_data_source.go index 3c9a740..92417bd 100644 --- a/internal/provider/blueprint_data_source.go +++ b/internal/provider/blueprint_data_source.go @@ -29,7 +29,7 @@ func (d *BlueprintDataSource) Metadata(_ context.Context, req datasource.Metadat func (d *BlueprintDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: "A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to:\n\n- Define which options are available for properties of your resource(s).\n- Apply gaurdrails to your resource(s) to prevent misconfiguration.\n- Define what information to collect from your developers before provisioning the resource.\n\nOne a blueprint is configured and published, it becomes available for use in your Resourcely service catalog.\n\nThe template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template.", + MarkdownDescription: "A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to:\n\n- Define which options are available for properties of your resource(s).\n- Apply gaurdrails to your resource(s) to prevent misconfiguration.\n- Define what information to collect from your developers before provisioning the resource.\n\nOnce a blueprint is configured and published, it becomes available for use in your Resourcely service catalog.\n\nThe template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ diff --git a/internal/provider/blueprint_resource.go b/internal/provider/blueprint_resource.go index 2faaca0..f643f5c 100644 --- a/internal/provider/blueprint_resource.go +++ b/internal/provider/blueprint_resource.go @@ -51,7 +51,7 @@ func (r *BlueprintResource) Schema( resp *resource.SchemaResponse, ) { resp.Schema = schema.Schema{ - MarkdownDescription: "A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to:\n\n- Define which options are available for properties of your resource(s).\n- Apply gaurdrails to your resource(s) to prevent misconfiguration.\n- Define what information to collect from your developers before provisioning the resource.\n\nOne a blueprint is configured and published, it becomes available for use in your Resourcely service catalog.\n\nThe template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template.", + MarkdownDescription: "A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to:\n\n- Define which options are available for properties of your resource(s).\n- Apply gaurdrails to your resource(s) to prevent misconfiguration.\n- Define what information to collect from your developers before provisioning the resource.\n\nOnce a blueprint is configured and published, it becomes available for use in your Resourcely service catalog.\n\nThe template is specified using Resourcely's TFT templating language. See the [Authoring Your Own Blueprints](https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints) docs for details about TFT. The [Resourcely Foundry](https://portal.resourcely.io/foundry?mode=blueprint) provides an IDE to assist with authoring the template.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ MarkdownDescription: "UUID for the current version of the blueprint.", diff --git a/internal/provider/context_question_data_source.go b/internal/provider/context_question_data_source.go index 5a43ecb..46289e5 100644 --- a/internal/provider/context_question_data_source.go +++ b/internal/provider/context_question_data_source.go @@ -30,7 +30,7 @@ func (d *ContextQuestionDataSource) Metadata(_ context.Context, req datasource.M func (d *ContextQuestionDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: "A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource.\n\nSoime examples include:\n\n-What type of data will be stored in this infrastructure?\n- What application is this infrastructure associated with?\n- What is the email address the person/team responsible for this infrastructure?\n\nThree types of context questions are supported:\n\n- Text\n- Single Choice\n- Multiple Choice\n", + MarkdownDescription: "A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource.\n\nSome examples include:\n\n- What type of data will be stored in this infrastructure?\n- What application is this infrastructure associated with?\n- What is the email address the person/team responsible for this infrastructure?\n\nThree types of context questions are supported:\n\n- Text\n- Single Choice\n- Multiple Choice\n", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ MarkdownDescription: "UUID for the current version of this context question.", diff --git a/internal/provider/context_question_resource.go b/internal/provider/context_question_resource.go index 9c42d31..04342c4 100644 --- a/internal/provider/context_question_resource.go +++ b/internal/provider/context_question_resource.go @@ -46,7 +46,7 @@ func (r *ContextQuestionResource) Metadata(_ context.Context, req resource.Metad func (r *ContextQuestionResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: "A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource.\n\nSoime examples include:\n\n-What type of data will be stored in this infrastructure?\n- What application is this infrastructure associated with?\n- What is the email address the person/team responsible for this infrastructure?\n\nThree types of context questions are supported:\n\n- Text\n- Single Choice\n- Multiple Choice\n", + MarkdownDescription: "A [context question](https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values) is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource.\n\nSome examples include:\n\n- What type of data will be stored in this infrastructure?\n- What application is this infrastructure associated with?\n- What is the email address the person/team responsible for this infrastructure?\n\nThree types of context questions are supported:\n\n- Text\n- Single Choice\n- Multiple Choice\n", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ MarkdownDescription: "UUID for the current version of the context question.", From 9228a2a805e4cf592be420a43212061b5ad2b6f5 Mon Sep 17 00:00:00 2001 From: "David R. Bild" Date: Mon, 25 Nov 2024 16:19:08 -0600 Subject: [PATCH 10/10] docs: remove description from frontmatter According to https://developer.hashicorp.com/terraform/registry/providers/docs#yaml-frontmatter, the frontmatter does not support a description field. Regardless, we place the description as the first section each document. --- docs/data-sources/blueprint.md | 5 ----- docs/data-sources/context_question.md | 6 ------ docs/data-sources/global_value.md | 2 -- docs/data-sources/guardrail.md | 4 ---- docs/index.md | 2 -- docs/resources/blueprint.md | 5 ----- docs/resources/context_question.md | 6 ------ docs/resources/global_value.md | 3 --- docs/resources/guardrail.md | 5 ----- templates/data-sources/blueprint.md.tmpl | 2 -- templates/data-sources/context_question.md.tmpl | 2 -- templates/data-sources/global_value.md.tmpl | 2 -- templates/data-sources/guardrail.md.tmpl | 2 -- templates/index.md.tmpl | 2 -- templates/resources/blueprint.md.tmpl | 2 -- templates/resources/context_question.md.tmpl | 2 -- templates/resources/global_value.md.tmpl | 2 -- templates/resources/guardrail.md.tmpl | 2 -- 18 files changed, 56 deletions(-) diff --git a/docs/data-sources/blueprint.md b/docs/data-sources/blueprint.md index c30a4c9..5183581 100644 --- a/docs/data-sources/blueprint.md +++ b/docs/data-sources/blueprint.md @@ -1,11 +1,6 @@ --- page_title: "resourcely_blueprint Data Source - terraform-provider-resourcely" subcategory: "" -description: |- - A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: - Define which options are available for properties of your resource(s).Apply gaurdrails to your resource(s) to prevent misconfiguration.Define what information to collect from your developers before provisioning the resource. - Once a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. - The template is specified using Resourcely's TFT templating language. See the Authoring Your Own Blueprints https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints docs for details about TFT. The Resourcely Foundry https://portal.resourcely.io/foundry?mode=blueprint provides an IDE to assist with authoring the template. --- # resourcely_blueprint (Data Source) diff --git a/docs/data-sources/context_question.md b/docs/data-sources/context_question.md index 522d852..8c158c9 100644 --- a/docs/data-sources/context_question.md +++ b/docs/data-sources/context_question.md @@ -1,12 +1,6 @@ --- page_title: "resourcely_context_question Data Source - terraform-provider-resourcely" subcategory: "" -description: |- - A context question https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. - Some examples include: - What type of data will be stored in this infrastructure?What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? - Three types of context questions are supported: - TextSingle ChoiceMultiple Choice --- # resourcely_context_question (Data Source) diff --git a/docs/data-sources/global_value.md b/docs/data-sources/global_value.md index 429dffa..c0a75d6 100644 --- a/docs/data-sources/global_value.md +++ b/docs/data-sources/global_value.md @@ -1,8 +1,6 @@ --- page_title: "resourcely_global_value Data Source - terraform-provider-resourcely" subcategory: "" -description: |- - A global value https://docs.resourcely.io/concepts/other-features-and-settings/global-values allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc. --- # resourcely_global_value (Data Source) diff --git a/docs/data-sources/guardrail.md b/docs/data-sources/guardrail.md index 2ce2d6a..1119139 100644 --- a/docs/data-sources/guardrail.md +++ b/docs/data-sources/guardrail.md @@ -1,10 +1,6 @@ --- page_title: "resourcely_guardrail Data Source - terraform-provider-resourcely" subcategory: "" -description: |- - A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. Some examples of guardrails include: - Require approval for making a public S3 bucketRestrict the allowed compute instance types or images - Guardrails are specified using the Really policy language https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails. --- # resourcely_guardrail (Data Source) diff --git a/docs/index.md b/docs/index.md index 9c201cb..c45b9af 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,5 @@ --- page_title: "Provider: resourcely" -description: |- - Manage Resourcely blueprints, guardrails, global values, and more through Terraform. --- # RESOURCELY Provider diff --git a/docs/resources/blueprint.md b/docs/resources/blueprint.md index cd75f26..09abe22 100644 --- a/docs/resources/blueprint.md +++ b/docs/resources/blueprint.md @@ -1,11 +1,6 @@ --- page_title: "resourcely_blueprint Resource - terraform-provider-resourcely" subcategory: "" -description: |- - A blueprint is a configuration template used to provision cloud infrastructure resources. Blueprints allow you to: - Define which options are available for properties of your resource(s).Apply gaurdrails to your resource(s) to prevent misconfiguration.Define what information to collect from your developers before provisioning the resource. - Once a blueprint is configured and published, it becomes available for use in your Resourcely service catalog. - The template is specified using Resourcely's TFT templating language. See the Authoring Your Own Blueprints https://docs.resourcely.io/build/setting-up-blueprints/authoring-your-own-blueprints docs for details about TFT. The Resourcely Foundry https://portal.resourcely.io/foundry?mode=blueprint provides an IDE to assist with authoring the template. --- # resourcely_blueprint (Resource) diff --git a/docs/resources/context_question.md b/docs/resources/context_question.md index 7c3f886..f9298b6 100644 --- a/docs/resources/context_question.md +++ b/docs/resources/context_question.md @@ -1,12 +1,6 @@ --- page_title: "resourcely_context_question Resource - terraform-provider-resourcely" subcategory: "" -description: |- - A context question https://docs.resourcely.io/concepts/other-features-and-settings/global-context-and-values is used to gather data from developers before provisioning a resource. They are designed to gather and store insightful data related to the resource. - Some examples include: - What type of data will be stored in this infrastructure?What application is this infrastructure associated with?What is the email address the person/team responsible for this infrastructure? - Three types of context questions are supported: - TextSingle ChoiceMultiple Choice --- # resourcely_context_question (Resource) diff --git a/docs/resources/global_value.md b/docs/resources/global_value.md index bdec65f..3b2d2c2 100644 --- a/docs/resources/global_value.md +++ b/docs/resources/global_value.md @@ -1,9 +1,6 @@ --- page_title: "resourcely_global_value Resource - terraform-provider-resourcely" subcategory: "" -description: |- - A global value https://docs.resourcely.io/concepts/other-features-and-settings/global-values allows admins to define custom drop-downs for customizing Terraform infrastructure resource properties before they are provisioned. They are useful for providing access to lists of relatively static values like VPC IDs, allowed regions, department or team names, etc. - This global value API does not support deletion. Deleting the Terraform resource will remove the resource from the Terraform state file, but will not actually delete the global value entity. Set is_deprecated = true to tell Resourcely that this global value should no longer be used by new blueprints or guardrails. --- # resourcely_global_value (Resource) diff --git a/docs/resources/guardrail.md b/docs/resources/guardrail.md index 18adf8a..0385396 100644 --- a/docs/resources/guardrail.md +++ b/docs/resources/guardrail.md @@ -1,11 +1,6 @@ --- page_title: "resourcely_guardrail Resource - terraform-provider-resourcely" subcategory: "" -description: |- - A guardrail governs how cloud resources can be created and altered, preventing infrastructure misconfiguration. Before infrastructure is provisioned, Resourcely examines the changes being made and prevents a merge if any guardrail requirements are violated. - Some examples of guardrails include: - Require approval for making a public S3 bucketRestrict the allowed compute instance types or images - Guardrails are specified using the Really policy language https://docs.resourcely.io/build/setting-up-guardrails/authoring-your-own-guardrails. --- # resourcely_guardrail (Resource) diff --git a/templates/data-sources/blueprint.md.tmpl b/templates/data-sources/blueprint.md.tmpl index be3ff70..c0da8da 100644 --- a/templates/data-sources/blueprint.md.tmpl +++ b/templates/data-sources/blueprint.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/data-sources/context_question.md.tmpl b/templates/data-sources/context_question.md.tmpl index be3ff70..c0da8da 100644 --- a/templates/data-sources/context_question.md.tmpl +++ b/templates/data-sources/context_question.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/data-sources/global_value.md.tmpl b/templates/data-sources/global_value.md.tmpl index be3ff70..c0da8da 100644 --- a/templates/data-sources/global_value.md.tmpl +++ b/templates/data-sources/global_value.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/data-sources/guardrail.md.tmpl b/templates/data-sources/guardrail.md.tmpl index be3ff70..c0da8da 100644 --- a/templates/data-sources/guardrail.md.tmpl +++ b/templates/data-sources/guardrail.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index 3d1eb67..9dbd78f 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -1,7 +1,5 @@ --- page_title: "Provider: resourcely" -description: |- - Manage Resourcely blueprints, guardrails, global values, and more through Terraform. --- # {{ .ProviderShortName | upper }} Provider diff --git a/templates/resources/blueprint.md.tmpl b/templates/resources/blueprint.md.tmpl index 7870a47..7f22faa 100644 --- a/templates/resources/blueprint.md.tmpl +++ b/templates/resources/blueprint.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/resources/context_question.md.tmpl b/templates/resources/context_question.md.tmpl index bfa42c4..eb869ca 100644 --- a/templates/resources/context_question.md.tmpl +++ b/templates/resources/context_question.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/resources/global_value.md.tmpl b/templates/resources/global_value.md.tmpl index 635b6ef..7754ea5 100644 --- a/templates/resources/global_value.md.tmpl +++ b/templates/resources/global_value.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}}) diff --git a/templates/resources/guardrail.md.tmpl b/templates/resources/guardrail.md.tmpl index 5fa6c9e..f260ec0 100644 --- a/templates/resources/guardrail.md.tmpl +++ b/templates/resources/guardrail.md.tmpl @@ -1,8 +1,6 @@ --- page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" subcategory: "" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} --- # {{.Name}} ({{.Type}})