From 70ba2f374fab9bf7b4181e48483dadab76af5c7c Mon Sep 17 00:00:00 2001 From: Sivaanand Murugesan Date: Tue, 22 Oct 2024 18:29:23 +0530 Subject: [PATCH 1/3] PLT-1402:Added ssh_key management support into terrafrom --- docs/data-sources/ssh_key.md | 26 ++++ docs/resources/ssh_key.md | 55 ++++++++ .../spectrocloud_ssh_key/providers.tf | 14 ++ .../spectrocloud_ssh_key/resource.tf | 10 ++ .../terraform.template.tfvars | 4 + .../spectrocloud_ssh_key/variables.tf | 13 ++ .../spectrocloud_ssh_key/providers.tf | 14 ++ .../spectrocloud_ssh_key/resource.tf | 10 ++ .../terraform.template.tfvars | 4 + .../spectrocloud_ssh_key/variables.tf | 18 +++ spectrocloud/data_source_ssh_key.go | 73 ++++++++++ spectrocloud/provider.go | 2 + spectrocloud/resource_ssh_key.go | 133 ++++++++++++++++++ templates/resources/ssh_key.md.tmpl | 31 ++++ 14 files changed, 407 insertions(+) create mode 100644 docs/data-sources/ssh_key.md create mode 100644 docs/resources/ssh_key.md create mode 100644 examples/data-sources/spectrocloud_ssh_key/providers.tf create mode 100644 examples/data-sources/spectrocloud_ssh_key/resource.tf create mode 100644 examples/data-sources/spectrocloud_ssh_key/terraform.template.tfvars create mode 100644 examples/data-sources/spectrocloud_ssh_key/variables.tf create mode 100644 examples/resources/spectrocloud_ssh_key/providers.tf create mode 100644 examples/resources/spectrocloud_ssh_key/resource.tf create mode 100644 examples/resources/spectrocloud_ssh_key/terraform.template.tfvars create mode 100644 examples/resources/spectrocloud_ssh_key/variables.tf create mode 100644 spectrocloud/data_source_ssh_key.go create mode 100644 spectrocloud/resource_ssh_key.go create mode 100644 templates/resources/ssh_key.md.tmpl diff --git a/docs/data-sources/ssh_key.md b/docs/data-sources/ssh_key.md new file mode 100644 index 00000000..cde75374 --- /dev/null +++ b/docs/data-sources/ssh_key.md @@ -0,0 +1,26 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "spectrocloud_ssh_key Data Source - terraform-provider-spectrocloud" +subcategory: "" +description: |- + +--- + +# spectrocloud_ssh_key (Data Source) + + + + + + +## Schema + +### Optional + +- `context` (String) The context of the cluster profile. Allowed values are `project` or `tenant`. Default value is `project`. If the `project` context is specified, the project name will sourced from the provider configuration parameter [`project_name`](https://registry.terraform.io/providers/spectrocloud/spectrocloud/latest/docs#schema). +- `id` (String) The Id of the SSH key resource. +- `name` (String) The name of the SSH key resource. + +### Read-Only + +- `ssh_key` (String, Sensitive) The SSH key value. diff --git a/docs/resources/ssh_key.md b/docs/resources/ssh_key.md new file mode 100644 index 00000000..ef562bb0 --- /dev/null +++ b/docs/resources/ssh_key.md @@ -0,0 +1,55 @@ +--- +page_title: "spectrocloud_ssh_key Resource - terraform-provider-spectrocloud" +subcategory: "" +description: |- + +--- + +# spectrocloud_ssh_key (Resource) + + + +You can learn more about managing ssh key by reviewing the [Create and Manage DNS Mappings](https://docs.spectrocloud.com/clusters/cluster-management/ssh-keys/) guide. + +## Example Usage + +An example of creating an ssh key assets in project or tenant context. + +```hcl +data "spectrocloud_ssh_key" "ssh_project" { + name = "test-tf-ssh" + context = "project" +} + +resource "spectrocloud_ssh_key" "ssh_tenant" { + name = "ssh-dev-1" + context = "tenant" + ssh_key = data.spectrocloud_ssh_key.ssh_project.ssh_key +} +``` + + +## Schema + +### Required + +- `name` (String) The name of the SSH key resource. +- `ssh_key` (String, Sensitive) The SSH key value. + +### Optional + +- `context` (String) The context of the cluster profile. Allowed values are `project` or `tenant`. Default value is `project`. If the `project` context is specified, the project name will sourced from the provider configuration parameter [`project_name`](https://registry.terraform.io/providers/spectrocloud/spectrocloud/latest/docs#schema). +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `timeouts` + +Optional: + +- `create` (String) +- `delete` (String) +- `update` (String) \ No newline at end of file diff --git a/examples/data-sources/spectrocloud_ssh_key/providers.tf b/examples/data-sources/spectrocloud_ssh_key/providers.tf new file mode 100644 index 00000000..4c109161 --- /dev/null +++ b/examples/data-sources/spectrocloud_ssh_key/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + spectrocloud = { + version = ">= 0.1" + source = "spectrocloud/spectrocloud" + } + } +} + +provider "spectrocloud" { + host = var.sc_host + api_key = var.sc_api_key + project_name = var.sc_project_name +} diff --git a/examples/data-sources/spectrocloud_ssh_key/resource.tf b/examples/data-sources/spectrocloud_ssh_key/resource.tf new file mode 100644 index 00000000..ed71f50e --- /dev/null +++ b/examples/data-sources/spectrocloud_ssh_key/resource.tf @@ -0,0 +1,10 @@ +data "spectrocloud_ssh_key" "ssh_project" { + name = "test-tf-ssh" + context = "project" +} + +resource "spectrocloud_ssh_key" "ssh_tenant" { + name = "ssh-dev-1" + context = "tenant" + ssh_key = data.spectrocloud_ssh_key.ssh_project.ssh_key +} \ No newline at end of file diff --git a/examples/data-sources/spectrocloud_ssh_key/terraform.template.tfvars b/examples/data-sources/spectrocloud_ssh_key/terraform.template.tfvars new file mode 100644 index 00000000..c7e9d50b --- /dev/null +++ b/examples/data-sources/spectrocloud_ssh_key/terraform.template.tfvars @@ -0,0 +1,4 @@ +# Spectro Cloud credentials +sc_host = "{Enter Spectro Cloud API Host}" #e.g: api.spectrocloud.com (for SaaS) +sc_api_key = "{Enter Spectro Cloud API Key}" +sc_project_name = "{Enter Spectro Cloud Project Name}" #e.g: Default \ No newline at end of file diff --git a/examples/data-sources/spectrocloud_ssh_key/variables.tf b/examples/data-sources/spectrocloud_ssh_key/variables.tf new file mode 100644 index 00000000..e89ad263 --- /dev/null +++ b/examples/data-sources/spectrocloud_ssh_key/variables.tf @@ -0,0 +1,13 @@ +variable "sc_host" { + description = "Spectro Cloud Endpoint" + default = "api.spectrocloud.com" +} + +variable "sc_api_key" { + description = "Spectro Cloud API key" +} + +variable "sc_project_name" { + description = "Spectro Cloud Project (e.g: Default)" + default = "Default" +} \ No newline at end of file diff --git a/examples/resources/spectrocloud_ssh_key/providers.tf b/examples/resources/spectrocloud_ssh_key/providers.tf new file mode 100644 index 00000000..4c109161 --- /dev/null +++ b/examples/resources/spectrocloud_ssh_key/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + spectrocloud = { + version = ">= 0.1" + source = "spectrocloud/spectrocloud" + } + } +} + +provider "spectrocloud" { + host = var.sc_host + api_key = var.sc_api_key + project_name = var.sc_project_name +} diff --git a/examples/resources/spectrocloud_ssh_key/resource.tf b/examples/resources/spectrocloud_ssh_key/resource.tf new file mode 100644 index 00000000..b8f824cb --- /dev/null +++ b/examples/resources/spectrocloud_ssh_key/resource.tf @@ -0,0 +1,10 @@ +resource "spectrocloud_ssh_key" "ssh_project" { + name = "ssh-dev-1-project" + context = "project" + ssh_key = var.ssh_key_value +} +resource "spectrocloud_ssh_key" "ssh_tenant" { + name = "ssh-dev-1" + context = "tenant" + ssh_key = var.ssh_key_value +} \ No newline at end of file diff --git a/examples/resources/spectrocloud_ssh_key/terraform.template.tfvars b/examples/resources/spectrocloud_ssh_key/terraform.template.tfvars new file mode 100644 index 00000000..c7e9d50b --- /dev/null +++ b/examples/resources/spectrocloud_ssh_key/terraform.template.tfvars @@ -0,0 +1,4 @@ +# Spectro Cloud credentials +sc_host = "{Enter Spectro Cloud API Host}" #e.g: api.spectrocloud.com (for SaaS) +sc_api_key = "{Enter Spectro Cloud API Key}" +sc_project_name = "{Enter Spectro Cloud Project Name}" #e.g: Default \ No newline at end of file diff --git a/examples/resources/spectrocloud_ssh_key/variables.tf b/examples/resources/spectrocloud_ssh_key/variables.tf new file mode 100644 index 00000000..7bebf92c --- /dev/null +++ b/examples/resources/spectrocloud_ssh_key/variables.tf @@ -0,0 +1,18 @@ +variable "sc_host" { + description = "Spectro Cloud Endpoint" + default = "api.spectrocloud.com" +} + +variable "sc_api_key" { + description = "Spectro Cloud API key" +} + +variable "sc_project_name" { + description = "Spectro Cloud Project (e.g: Default)" + default = "Default" +} + +variable "ssh_key_value" { + description = "ssh key value" + default = "ssh-rsa ...... == test@test.com" +} \ No newline at end of file diff --git a/spectrocloud/data_source_ssh_key.go b/spectrocloud/data_source_ssh_key.go new file mode 100644 index 00000000..46cca2bd --- /dev/null +++ b/spectrocloud/data_source_ssh_key.go @@ -0,0 +1,73 @@ +package spectrocloud + +import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/spectrocloud/palette-sdk-go/api/models" +) + +func dataSourceSSHKey() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceSSHKeyRead, + + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ConflictsWith: []string{"name"}, + Description: "The Id of the SSH key resource.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: "The name of the SSH key resource.", + }, + "ssh_key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + Description: "The SSH key value.", + }, + "context": { + Type: schema.TypeString, + Optional: true, + Default: "project", + ValidateFunc: validation.StringInSlice([]string{"project", "tenant"}, false), + Description: "The context of the cluster profile. Allowed values are `project` or `tenant`. " + + "Default value is `project`. " + PROJECT_NAME_NUANCE, + }, + }, + } +} + +func dataSourceSSHKeyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + sshKeyContext := d.Get("context").(string) + c := getV1ClientWithResourceContext(m, sshKeyContext) + var diags diag.Diagnostics + id := d.Get("id").(string) + name := d.Get("name").(string) + var sshKey *models.V1UserAssetSSH + var err error + if id != "" { + sshKey, err = c.GetSSHKey(d.Id()) + } else if name != "" { + sshKey, err = c.GetSSHKeyByName(name) + } + if err != nil { + return diag.FromErr(err) + } + d.SetId(sshKey.Metadata.UID) + err = d.Set("name", sshKey.Metadata.Name) + if err != nil { + return nil + } + err = d.Set("ssh_key", sshKey.Spec.PublicKey) + if err != nil { + return nil + } + return diags +} diff --git a/spectrocloud/provider.go b/spectrocloud/provider.go index 691ead40..f0a0732f 100644 --- a/spectrocloud/provider.go +++ b/spectrocloud/provider.go @@ -137,6 +137,7 @@ func New(_ string) func() *schema.Provider { "spectrocloud_workspace": resourceWorkspace(), "spectrocloud_alert": resourceAlert(), + "spectrocloud_ssh_key": resourceSSHKey(), }, DataSourcesMap: map[string]*schema.Resource{ "spectrocloud_user": dataSourceUser(), @@ -176,6 +177,7 @@ func New(_ string) func() *schema.Provider { "spectrocloud_private_cloud_gateway": dataSourcePCG(), "spectrocloud_ippool": dataSourcePrivateCloudGatewayIpPool(), + "spectrocloud_ssh_key": dataSourceSSHKey(), }, ConfigureContextFunc: providerConfigure, } diff --git a/spectrocloud/resource_ssh_key.go b/spectrocloud/resource_ssh_key.go new file mode 100644 index 00000000..5933f131 --- /dev/null +++ b/spectrocloud/resource_ssh_key.go @@ -0,0 +1,133 @@ +package spectrocloud + +import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/spectrocloud/palette-sdk-go/api/models" + "time" +) + +func resourceSSHKey() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceSSHKeyCreate, + ReadContext: resourceSSHKeyRead, + UpdateContext: resourceSSHKeyUpdate, + DeleteContext: resourceSSHKeyDelete, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + }, + SchemaVersion: 2, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "The name of the SSH key resource.", + }, + "ssh_key": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + Description: "The SSH key value.", + }, + "context": { + Type: schema.TypeString, + Optional: true, + Default: "project", + ValidateFunc: validation.StringInSlice([]string{"project", "tenant"}, false), + Description: "The context of the cluster profile. Allowed values are `project` or `tenant`. " + + "Default value is `project`. " + PROJECT_NAME_NUANCE, + }, + }, + } +} + +func toSSHKey(d *schema.ResourceData) (*models.V1UserAssetSSH, error) { + return &models.V1UserAssetSSH{ + Metadata: &models.V1ObjectMeta{ + Name: d.Get("name").(string), + }, + Spec: &models.V1UserAssetSSHSpec{ + PublicKey: d.Get("ssh_key").(string), + }, + }, nil +} + +func flattenSSHKey(sshKey *models.V1UserAssetSSH, d *schema.ResourceData) error { + err := d.Set("name", sshKey.Metadata.Name) + if err != nil { + return err + } + err = d.Set("ssh_key", sshKey.Spec.PublicKey) + if err != nil { + return err + } + return nil +} + +func resourceSSHKeyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + sshKeyContext := d.Get("context").(string) + c := getV1ClientWithResourceContext(m, sshKeyContext) + var diags diag.Diagnostics + sshKey, err := toSSHKey(d) + if err != nil { + return diag.FromErr(err) + } + uid, err := c.CreateSSHKey(sshKey) + if err != nil { + return diag.FromErr(err) + } + d.SetId(uid) + return diags +} + +func resourceSSHKeyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + sshKeyContext := d.Get("context").(string) + c := getV1ClientWithResourceContext(m, sshKeyContext) + var diags diag.Diagnostics + + sshKey, err := c.GetSSHKey(d.Id()) + if err != nil { + return diag.FromErr(err) + } else if sshKey == nil { + // Deleted - Terraform will recreate it + d.SetId("") + return diags + } + err = flattenSSHKey(sshKey, d) + if err != nil { + return diag.FromErr(err) + } + return diags +} + +func resourceSSHKeyUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + sshKeyContext := d.Get("context").(string) + c := getV1ClientWithResourceContext(m, sshKeyContext) + var diags diag.Diagnostics + sshKey, err := toSSHKey(d) + if err != nil { + return diag.FromErr(err) + } + err = c.UpdateSSHKey(d.Id(), sshKey) + if err != nil { + return diag.FromErr(err) + } + return diags +} + +func resourceSSHKeyDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + sshKeyContext := d.Get("context").(string) + c := getV1ClientWithResourceContext(m, sshKeyContext) + var diags diag.Diagnostics + + err := c.DeleteSSHKey(d.Id()) + if err != nil { + return diag.FromErr(err) + } + return diags +} diff --git a/templates/resources/ssh_key.md.tmpl b/templates/resources/ssh_key.md.tmpl new file mode 100644 index 00000000..58fce6ab --- /dev/null +++ b/templates/resources/ssh_key.md.tmpl @@ -0,0 +1,31 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} + +You can learn more about managing ssh key by reviewing the [Create and Manage DNS Mappings](https://docs.spectrocloud.com/clusters/cluster-management/ssh-keys/) guide. + +## Example Usage + +An example of creating an ssh key assets in project or tenant context. + +```hcl +data "spectrocloud_ssh_key" "ssh_project" { + name = "test-tf-ssh" + context = "project" +} + +resource "spectrocloud_ssh_key" "ssh_tenant" { + name = "ssh-dev-1" + context = "tenant" + ssh_key = data.spectrocloud_ssh_key.ssh_project.ssh_key +} +``` + +{{ .SchemaMarkdown | trimspace }} \ No newline at end of file From 45ae31f38f30838913749fd04f90f515d8d7098e Mon Sep 17 00:00:00 2001 From: Sivaanand Murugesan Date: Tue, 22 Oct 2024 21:44:56 +0530 Subject: [PATCH 2/3] updated sdk --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 78a1cd7b..24e2cff1 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/robfig/cron v1.2.0 github.com/spectrocloud/gomi v1.14.1-0.20240214074114-c19394812368 github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d - github.com/spectrocloud/palette-sdk-go v0.0.0-20241018151815-6925f4d3d199 + github.com/spectrocloud/palette-sdk-go v0.0.0-20241022161234-3782615736bb github.com/stretchr/testify v1.9.0 gotest.tools v2.2.0+incompatible k8s.io/api v0.23.5 diff --git a/go.sum b/go.sum index e1154f30..7c250e31 100644 --- a/go.sum +++ b/go.sum @@ -602,6 +602,8 @@ github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d h1:OMRbHxMJ1a github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d/go.mod h1:MktpRPnSXDTHsQrFSD+daJFQ1zMLSR+1gWOL31jVvWE= github.com/spectrocloud/palette-sdk-go v0.0.0-20241018151815-6925f4d3d199 h1:YlU+FfzCWusdufvR7IanDHg5ZURM0Z79enWpD36ohf0= github.com/spectrocloud/palette-sdk-go v0.0.0-20241018151815-6925f4d3d199/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U= +github.com/spectrocloud/palette-sdk-go v0.0.0-20241022161234-3782615736bb h1:LVeVFAMVdZRhtn1VY3DnDi32ts90r8/RXP5+1RZBZEA= +github.com/spectrocloud/palette-sdk-go v0.0.0-20241022161234-3782615736bb/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= From a5bd8f095dee184594576d97e486a42c44940fd0 Mon Sep 17 00:00:00 2001 From: Sivaanand Murugesan Date: Tue, 22 Oct 2024 21:52:00 +0530 Subject: [PATCH 3/3] fix reviewable --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 7c250e31..f234f5f9 100644 --- a/go.sum +++ b/go.sum @@ -600,8 +600,6 @@ github.com/spectrocloud/gomi v1.14.1-0.20240214074114-c19394812368 h1:eY0BOyEbGu github.com/spectrocloud/gomi v1.14.1-0.20240214074114-c19394812368/go.mod h1:LlZ9We4kDaELYi7Is0SVmnySuDhwphJLS6ZT4wXxFIk= github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d h1:OMRbHxMJ1a+G1BYzvUYuMM0wLkYJPdnEOFx16faQ/UY= github.com/spectrocloud/hapi v1.14.1-0.20240214071352-81f589b1d86d/go.mod h1:MktpRPnSXDTHsQrFSD+daJFQ1zMLSR+1gWOL31jVvWE= -github.com/spectrocloud/palette-sdk-go v0.0.0-20241018151815-6925f4d3d199 h1:YlU+FfzCWusdufvR7IanDHg5ZURM0Z79enWpD36ohf0= -github.com/spectrocloud/palette-sdk-go v0.0.0-20241018151815-6925f4d3d199/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U= github.com/spectrocloud/palette-sdk-go v0.0.0-20241022161234-3782615736bb h1:LVeVFAMVdZRhtn1VY3DnDi32ts90r8/RXP5+1RZBZEA= github.com/spectrocloud/palette-sdk-go v0.0.0-20241022161234-3782615736bb/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=