diff --git a/gridscale/datasource_gridscale_k8s.go b/gridscale/datasource_gridscale_k8s.go new file mode 100644 index 000000000..368e07026 --- /dev/null +++ b/gridscale/datasource_gridscale_k8s.go @@ -0,0 +1,111 @@ +package gridscale + +import ( + "context" + "fmt" + "time" + + "github.com/gridscale/gsclient-go/v3" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func dataSourceGridscaleK8s() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGridscaleK8sRead, + Schema: map[string]*schema.Schema{ + "resource_id": { + Type: schema.TypeString, + Required: true, + Description: "ID of a resource", + ValidateFunc: validation.NoZeroValues, + }, + "name": { + Type: schema.TypeString, + Description: "The human-readable name of the object. It supports the full UTF-8 character set, with a maximum of 64 characters", + Computed: true, + }, + "kubeconfig": { + Type: schema.TypeString, + Description: "K8s config data", + Computed: true, + Sensitive: true, + }, + "k8s_private_network_uuid": { + Type: schema.TypeString, + Description: "Private network UUID which k8s nodes are attached to. It can be used to attach other PaaS/VMs.", + Computed: true, + }, + "labels": { + Type: schema.TypeSet, + Description: "List of labels.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceGridscaleK8sRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gsclient.Client) + id := d.Get("resource_id").(string) + d.SetId(id) + errorPrefix := fmt.Sprintf("read k8s (%s) resource -", id) + paas, err := client.GetPaaSService(context.Background(), id) + + if err != nil { + if requestError, ok := err.(gsclient.RequestError); ok { + if requestError.StatusCode == 404 { + d.SetId("") + return nil + } + } + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + creds := paas.Properties.Credentials + if len(creds) > 0 { + // if expiration_time of kubeconfig is reached, renew it and get new kubeconfig + if creds[0].ExpirationTime.Before(time.Now()) { + err = client.RenewK8sCredentials(context.Background(), d.Id()) + if err != nil { + return fmt.Errorf("%s error renewing k8s kubeconfig: %v", errorPrefix, err) + } + paas, err = client.GetPaaSService(context.Background(), d.Id()) + if err != nil { + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + creds = paas.Properties.Credentials + } + if err = d.Set("kubeconfig", creds[0].KubeConfig); err != nil { + return fmt.Errorf("%s error setting kubeconfig: %v", errorPrefix, err) + } + } + + if err = d.Set("name", paas.Properties.Name); err != nil { + return fmt.Errorf("%s error setting name: %v", errorPrefix, err) + } + if err = d.Set("kubeconfig", creds[0].KubeConfig); err != nil { + return fmt.Errorf("%s error setting name: %v", errorPrefix, err) + } + if err = d.Set("labels", paas.Properties.Labels); err != nil { + return fmt.Errorf("%s error setting labels: %v", errorPrefix, err) + } + networks, err := client.GetNetworkList(context.Background()) + if err != nil { + return fmt.Errorf("%s error getting networks: %v", errorPrefix, err) + } + // find the network with the label that matches the k8s label + k8sLabel := fmt.Sprintf("%s%s", k8sLabelPrefix, d.Id()) +NETWORK_LOOOP: + for _, network := range networks { + for _, label := range network.Properties.Labels { + if label == k8sLabel { + if err = d.Set("k8s_private_network_uuid", network.Properties.ObjectUUID); err != nil { + return fmt.Errorf("%s error setting k8s_private_network_uuid: %v", errorPrefix, err) + } + break NETWORK_LOOOP + } + } + } + return nil +} diff --git a/gridscale/datasource_gridscale_k8s_test.go b/gridscale/datasource_gridscale_k8s_test.go new file mode 100644 index 000000000..828a604c5 --- /dev/null +++ b/gridscale/datasource_gridscale_k8s_test.go @@ -0,0 +1,53 @@ +package gridscale + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDataSourceGridscaleK8sBasic(t *testing.T) { + name := fmt.Sprintf("object-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceGridscaleServerDestroyCheck, + Steps: []resource.TestStep{ + { + Config: testAccCheckDataSourceGridscaleK8sConfigBasic(name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.gridscale_k8s.test", "k8s_private_network_uuid"), + resource.TestCheckResourceAttrSet( + "data.gridscale_k8s.test", "kubeconfig"), + resource.TestCheckResourceAttrSet( + "data.gridscale_k8s.test", "labels"), + ), + }, + }, + }) +} + +func testAccCheckDataSourceGridscaleK8sConfigBasic(name string) string { + return fmt.Sprintf(` +resource "gridscale_k8s" "test" { + name = "%s" + release = "1.30" # instead, gsk_version can be set. + + node_pool { + name = "pool-0" + node_count = 2 + cores = 2 + memory = 4 + storage = 30 + storage_type = "storage_insane" + } +} + +data "gridscale_k8s" "test" { + resource_id = gridscale_k8s.test.id +}`, name) +} diff --git a/gridscale/provider.go b/gridscale/provider.go index af1b48872..57cb56e76 100644 --- a/gridscale/provider.go +++ b/gridscale/provider.go @@ -69,6 +69,7 @@ func Provider() *schema.Provider { "gridscale_backupschedule": dataSourceGridscaleStorageBackupSchedule(), "gridscale_paas": dataSourceGridscalePaaS(), "gridscale_paas_securityzone": dataSourceGridscalePaaSSecurityZone(), + "gridscale_k8s": dataSourceGridscaleK8s(), "gridscale_object_storage_accesskey": dataSourceGridscaleObjectStorage(), "gridscale_isoimage": dataSourceGridscaleISOImage(), "gridscale_firewall": dataSourceGridscaleFirewall(), diff --git a/website/docs/d/k8s.html.md b/website/docs/d/k8s.html.md new file mode 100644 index 000000000..44e15364e --- /dev/null +++ b/website/docs/d/k8s.html.md @@ -0,0 +1,44 @@ +--- +layout: "gridscale" +page_title: "gridscale: gridscale_k8s" +sidebar_current: "docs-gridscale-resource-k8s" +description: |- + Get data from a k8s cluster in gridscale. +--- + +# gridscale_k8s + + +Get information about a Gridscale Kubernetes cluster. + +## Example Usage + +```terraform +data "gridscale_k8s" "k8s-example" { + resource_id = "xxxx-xxxx-xxxx-xxxx" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `resource_id` - (Required) The UUID of the Kubernetes cluster. + +## Timeouts + +Timeouts configuration options (in seconds): +More info: [terraform.io/docs/configuration/resources.html#operation-timeouts](https://www.terraform.io/docs/configuration/resources.html#operation-timeouts) + +* `create` - (Default value is "45m" - 45 minutes) Used for creating a resource. +* `update` - (Default value is "45m" - 45 minutes) Used for updating a resource. +* `delete` - (Default value is "45m" - 45 minutes) Used for deleting a resource. + +## Attributes + +This resource exports the following attributes: + +* `name` - The human-readable name of the Kubernetes cluster. +* `labels` - See Argument Reference above. +* `kubeconfig` - The kubeconfig file content of the k8s cluster. +* `k8s_private_network_uuid` - Private network UUID which k8s nodes are attached to. It can be used to attach other PaaS/VMs. \ No newline at end of file diff --git a/website/gridscale.erb b/website/gridscale.erb index cb73ea882..316a17774 100644 --- a/website/gridscale.erb +++ b/website/gridscale.erb @@ -20,6 +20,9 @@ > gridscale_isoimage + > + gridscale_k8s + > gridscale_loadbalancer