Skip to content

add KMS enablement support to satellite cluster #6187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions examples/ibm-satellite/modules/cluster/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@ data "ibm_resource_group" "rg" {
name = var.resource_group
}

resource "ibm_resource_instance" "kms_instance1" {
name = "test_kms"
service = "kms"
plan = "tiered-pricing"
location = "us-south"
}

resource "ibm_kms_key" "test" {
instance_id = ibm_resource_instance.kms_instance1.guid
key_name = "test_root_key"
standard_key = false
force_delete = true
}

resource "ibm_satellite_cluster" "create_cluster" {
name = var.cluster
location = var.location
Expand All @@ -21,6 +35,12 @@ resource "ibm_satellite_cluster" "create_cluster" {

default_worker_pool_labels = var.default_wp_labels
tags = var.cluster_tags

kms_config {
instance_id = ibm_resource_instance.kms_instance1.guid
crk_id = ibm_kms_key.test.id
private_endpoint = false
}
}

data "ibm_satellite_cluster" "read_cluster" {
Expand Down
74 changes: 73 additions & 1 deletion ibm/service/satellite/resource_ibm_satellite_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,37 @@ func ResourceIBMSatelliteCluster() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
DiffSuppressFunc: flex.ApplyOnce,
},
"kms_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Description: "Enables KMS on a given cluster ",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"instance_id": {
Type: schema.TypeString,
Required: true,
Description: "ID of the KMS instance to use to encrypt the cluster.",
},
"crk_id": {
Type: schema.TypeString,
Required: true,
Description: "ID of the customer root key.",
},
"private_endpoint": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Specify this option to use the KMS public service endpoint.",
},
"account_id": {
Type: schema.TypeString,
Optional: true,
Description: "Account ID of KMS instance holder - if not provided, defaults to the account in use",
},
},
},
},
},
}
}
Expand Down Expand Up @@ -517,7 +548,7 @@ func resourceIBMSatelliteClusterCreate(d *schema.ResourceData, meta interface{})
return fmt.Errorf("[ERROR] Error waiting for getting cluster (%s) to be warning state: %s", clusterId, err)
}

return resourceIBMSatelliteClusterRead(d, meta)
return resourceIBMSatelliteClusterUpdate(d, meta)
}

func resourceIBMSatelliteClusterRead(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -787,6 +818,47 @@ func resourceIBMSatelliteClusterUpdate(d *schema.ResourceData, meta interface{})
}
}

if d.HasChange("kms_config") {
kmsConfig := v1.KmsEnableReq{}
kmsConfig.Cluster = clusterID
targetEnv := v1.ClusterHeader{}
if kms, ok := d.GetOk("kms_config"); ok {

kmsConfiglist := kms.([]interface{})

for _, l := range kmsConfiglist {
kmsMap, _ := l.(map[string]interface{})

//instance_id - Required field
instanceID := kmsMap["instance_id"].(string)
kmsConfig.Kms = instanceID

//crk_id - Required field
crk := kmsMap["crk_id"].(string)
kmsConfig.Crk = crk

//Read event - as its optional check for existence
if privateEndpoint := kmsMap["private_endpoint"]; privateEndpoint != nil {
endpoint := privateEndpoint.(bool)
kmsConfig.PrivateEndpoint = endpoint
}

//Read optional account id
if accountid := kmsMap["account_id"]; accountid != nil {
accountid_string := accountid.(string)
kmsConfig.AccountID = accountid_string
}
}
}

err = csClient.Kms().EnableKms(kmsConfig, targetEnv)
if err != nil {
log.Printf(
"An error occured during EnableKms (cluster: %s) error: %s", d.Id(), err)
return err
}
}

return resourceIBMSatelliteClusterRead(d, meta)
}

Expand Down
158 changes: 158 additions & 0 deletions ibm/service/satellite/resource_ibm_satellite_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,161 @@ func testAccCheckSatelliteEntitlementClusterCreate(clusterName, locationName, ma
}
`, locationName, managed_from, resource_group, resource_prefix, resource_prefix, region, resource_prefix, publicKey, resource_prefix, region, resource_prefix, host_provider, clusterName, operatingSystem)
}

func TestAccIBMSatelliteCluster_KmsEnable(t *testing.T) {
clusterName := fmt.Sprintf("terraform1_%d", acctest.RandIntRange(10, 100))
locationName := fmt.Sprintf("tf-satellitelocation-%d", acctest.RandIntRange(10, 100))
managed_from := "dal10"
operatingSystem := "REDHAT_8_64"
resource_group := "Default"
region := "us-south"
resource_prefix := "tf-satellite"
host_provider := "ibm"
publicKey := acc.SatelliteSSHPubKey
kmsInstanceName := fmt.Sprintf("kmsInstance_%d", acctest.RandIntRange(10, 100))
rootKeyName := fmt.Sprintf("rootKey_%d", acctest.RandIntRange(10, 100))

resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
CheckDestroy: testAccCheckSatelliteClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMSatelliteClusterKmsEnable(kmsInstanceName, rootKeyName, clusterName, locationName, managed_from, operatingSystem, resource_group, resource_prefix, region, publicKey, host_provider),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"ibm_satellite_cluster.create_cluster", "name", clusterName),
resource.TestCheckResourceAttr(
"ibm_satellite_cluster.create_cluster", "kms_config.#", "1"),
),
},
},
})
}

func testAccCheckIBMSatelliteClusterKmsEnable(kmsInstanceName, rootKeyName, clusterName, locationName, managed_from, operatingSystem, resource_group, resource_prefix, region, publicKey, host_provider string) string {
return fmt.Sprintf(`

resource "ibm_resource_instance" "kms_instance1" {
name = "%s"
service = "kms"
plan = "tiered-pricing"
location = "us-south"
}

resource "ibm_kms_key" "test" {
instance_id = "${ibm_resource_instance.kms_instance1.guid}"
key_name = "%s"
standard_key = false
force_delete = true
}

variable "location_zones" {
description = "Allocate your hosts across these three zones"
type = list(string)
default = ["us-south-1", "us-south-2", "us-south-3"]
}

data "ibm_is_image" "rhel8" {
name = "ibm-redhat-8-8-minimal-amd64-2"
}

resource "ibm_satellite_location" "location" {
location = "%s"
managed_from = "%s"
zones = var.location_zones
coreos_enabled = true
}

data "ibm_satellite_attach_host_script" "script" {
location = ibm_satellite_location.location.id
labels = ["env:prod"]
host_provider = "ibm"
}

data "ibm_resource_group" "resource_group" {
name = "%s"
}

resource "ibm_is_vpc" "satellite_vpc" {
name = "%s-vpc-1"
}

resource "ibm_is_subnet" "satellite_subnet" {
count = 3

name = "%s-subnet-${count.index}"
vpc = ibm_is_vpc.satellite_vpc.id
total_ipv4_address_count = 256
zone = "%s-${count.index + 1}"
}

resource "ibm_is_ssh_key" "satellite_ssh" {
name = "%s-ibm-ssh"
public_key = "%s"
}

resource "ibm_is_instance" "satellite_instance" {
count = 3

name = "%s-instance-${count.index}"
vpc = ibm_is_vpc.satellite_vpc.id
zone = "%s-${count.index + 1}"
image = data.ibm_is_image.rhel8.id
profile = "mx2-8x64"
keys = [ibm_is_ssh_key.satellite_ssh.id]
resource_group = data.ibm_resource_group.resource_group.id
user_data = data.ibm_satellite_attach_host_script.script.host_script

primary_network_interface {
subnet = ibm_is_subnet.satellite_subnet[count.index].id
}
}

resource "ibm_is_floating_ip" "satellite_ip" {
count = 3

name = "%s-fip-${count.index}"
target = ibm_is_instance.satellite_instance[count.index].primary_network_interface[0].id
}

resource "ibm_satellite_host" "assign_host" {
count = 3

location = ibm_satellite_location.location.id
host_id = element(ibm_is_instance.satellite_instance[*].name, count.index)
labels = ["env:prod"]
zone = element(var.location_zones, count.index)
host_provider = "%s"
}

resource "ibm_satellite_cluster" "create_cluster" {
name = "%s"
location = ibm_satellite_host.assign_host.0.location
enable_config_admin = true
kube_version = "4.13_openshift"
operating_system = "%s"
wait_for_worker_update = true
dynamic "zones" {
for_each = var.location_zones
content {
id = zones.value
}
}
default_worker_pool_labels = {
"test" = "test-pool1"
"test1" = "test-pool2"
}
kms_config {
instance_id = ibm_resource_instance.kms_instance1.guid
crk_id = ibm_kms_key.test.key_id
private_endpoint = false
}
}

data "ibm_satellite_cluster_worker_pool" "read_default_wp" {
name = "default"
cluster = ibm_satellite_cluster.create_cluster.id
}
`, kmsInstanceName, rootKeyName, locationName, managed_from, resource_group, resource_prefix, resource_prefix, region, resource_prefix, publicKey, resource_prefix, region, resource_prefix, host_provider, clusterName, operatingSystem)
}
64 changes: 46 additions & 18 deletions website/docs/r/satellite_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,46 @@ Create, update, or delete [IBM Cloud Satellite Cluster](https://cloud.ibm.com/do

```terraform
resource "ibm_satellite_cluster" "create_cluster" {
name = "%s"
location = var.location
enable_config_admin = true
kube_version = "4.6_openshift"
resource_group_id = data.ibm_resource_group.rg.id
wait_for_worker_update = true
dynamic "zones" {
for_each = var.zones
content {
id = zones.value
}
}
name = "%s"
location = var.location
enable_config_admin = true
kube_version = "4.6_openshift"
resource_group_id = data.ibm_resource_group.rg.id
wait_for_worker_update = true
dynamic "zones" {
for_each = var.zones
content {
id = zones.value
}
}
}

```

### Create a KMS Enabled satellite cluster:

```hcl
resource "ibm_satellite_cluster" "create_cluster" {
name = "%s"
location = var.location
enable_config_admin = true
kube_version = "4.6_openshift"
resource_group_id = data.ibm_resource_group.rg.id
wait_for_worker_update = true
dynamic "zones" {
for_each = var.zones
content {
id = zones.value
}
}
kms_config {
instance_id = "12043812-757f-4e1e-8436-6af3245e6a69"
crk_id = "0792853c-b9f9-4b35-9d9e-ffceab51d3c1"
private_endpoint = false
}
}
```

### Create satellite cluster with calico ip autodetection

```terraform
Expand Down Expand Up @@ -92,7 +116,7 @@ The `ibm_satellite_cluster` provides the following [Timeouts](https://www.terraf

## Argument reference

Review the argument references that you can specify for your resource.
Review the argument references that you can specify for your resource.

- `name` - (Required, String) The unique name for the new IBM Cloud Satellite cluster.
- `location` - (Required, String) The name or ID of the Satellite location.
Expand All @@ -105,17 +129,21 @@ Review the argument references that you can specify for your resource.
- `host_labels` - (Optional, Set(Strings)) Labels to add to the default worker pool, formatted as `cpu:4` key-value pairs. Satellite uses host labels to automatically assign hosts to worker pools with matching labels.
- `default_worker_pool_labels` - (Optional, String) The labels on all the workers in the default worker pool.
- `pull_secret` - (Optional, String) The Red Hat pull secret to create the OpenShift cluster.
- `zone` - (Optional, List) The zone for the worker pool in a multi-zone cluster.
- `zone` - (Optional, List) The zone for the worker pool in a multi-zone cluster.
- `infrastructure_topology` - (Optional, String) Specify whether the cluster should run a single worker node or the default number of worker nodes. Only works with kube version 4.11 and newer. To create a single-node cluster, specify 'single-replica'. To create a default cluster with multiple worker nodes, specify 'highly-available'. The 'highly-available' option is applied by default. Available options: single-replica, highly-available (default: "highly-available")
* `kms_config` - (Optional, list) Used to attach a key protect instance to a cluster. Nested `kms_config` block has the following structure:
* `instance_id` - The guid of the key protect instance.
* `crk_id` - Id of the customer root key (CRK).
* `private_endpoint` - Set this to true to configure the KMS private service endpoint. Default is false.

Nested scheme for `zone`:
Nested scheme for `zone`:
- `id` - The name of the zone.
- `resource_group_id` - (Optional, String) The ID of the resource group. You can retrieve the value from data source `ibm_resource_group`.
- `tags` - (Optional, Array of Strings) List of tags associated with this cluster.
- `wait_for_worker_update` - (Optional, Bool) Set to **true** to wait for kube version of woker nodes to update during the worker node kube version update. **NOTE** setting `wait_for_worker_update` to **false** is not recommended. This results in upgrading all the worker nodes in the cluster at the same time causing the cluster downtime.
- `patch_version` - (Optional, String) Set this to update the worker nodes with the required patch version.
The `patch_version` should be in the format - `patch_version_fixpack_version`. For more information, see [Kuberentes version](https://cloud.ibm.com/docs/containers?topic=containers-cs_versions).
**NOTE**: To update the patch/fixpack versions of the worker nodes, Run the command `ibmcloud ks workers -c <cluster_name_or_id> --output json`, fetch the required patch & fixpack versions from `kubeVersion.target` and set the patch_version parameter.
- `patch_version` - (Optional, String) Set this to update the worker nodes with the required patch version.
The `patch_version` should be in the format - `patch_version_fixpack_version`. For more information, see [Kuberentes version](https://cloud.ibm.com/docs/containers?topic=containers-cs_versions).
**NOTE**: To update the patch/fixpack versions of the worker nodes, Run the command `ibmcloud ks workers -c <cluster_name_or_id> --output json`, fetch the required patch & fixpack versions from `kubeVersion.target` and set the patch_version parameter.
- `retry_patch_version` - (Optional, Integer) This argument helps to retry the update of `patch_version` if the previous update fails. Increment the value to retry the update of `patch_version` on worker nodes.
- `tags` - (Optional, Array of Strings) Tags associated with the container cluster instance.
- `pod_subnet` - Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must be at least `/23` or larger. For more information, see [Configuring VPC subnets](https://cloud.ibm.com/docs/containers?topic=containers-vpc-subnets).
Expand Down