Skip to content

Commit b5ded88

Browse files
authored
Merge pull request #592 from mouellet/cluster-sync-nodes-ref
Add `nodes` attribute reference to `rancher2_cluster_sync` resource
2 parents eb57688 + 647d940 commit b5ded88

7 files changed

Lines changed: 308 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ ENHANCEMENTS:
1414
* Updated `rancher2_node_template.openstack_config` to support `boot_from_volume` and related arguments
1515
* Added `password` as valid `cluster_template_questions` type to `rancher2_cluster` resource
1616
* Preserve `cluster_template_answers` for `cluster_template_questions` of type `password` in `rancher2_cluster` resource to avoid misleading diffs
17+
* Added `nodes` attribute reference to `rancher2_cluster_sync` resource
1718

1819
BUG FIXES:
1920

docs/resources/cluster_sync.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,40 @@ The following attributes are exported:
9898
* `id` - (Computed) The ID of the resource. Same as `cluster_id` (string)
9999
* `default_project_id` - (Computed) Default project ID for the cluster sync (string)
100100
* `kube_config` - (Computed/Sensitive) Kube Config generated for the cluster sync (string)
101+
* `nodes` - (Computed) The cluster nodes (list).
101102
* `system_project_id` - (Computed) System project ID for the cluster sync (string)
102103

104+
## Nested blocks
105+
106+
### `nodes`
107+
108+
#### Arguments
109+
110+
* `annotations` - (Computed) Annotations of the node (map).
111+
* `capacity` - (Computed) The total resources of a node (map).
112+
* `cluster_id` - (Computed) The Cluster ID of the node (string).
113+
* `external_ip_address` - (Computed) The external IP address of the node (string).
114+
* `hostname` - (Computed) The hostname of the node (string).
115+
* `id` - (Computed) The ID of the node (string)
116+
* `ip_address` - (Computed) The private IP address of the node (string).
117+
* `labels` - (Computed) Labels of the node (map).
118+
* `name` - (Computed) The name of the node (string).
119+
* `node_pool_id` - (Computed) The Node Pool ID of the node (string).
120+
* `node_template_id` - (Computed) The Node Template ID of the node (string).
121+
* `provider_id` - (Computed) The Provider ID of the node (string).
122+
* `requested_hostname` - (Computed) The requested hostname (string).
123+
* `roles` - (Computed) Roles of the node. `controlplane`, `etcd` and `worker`. (list)
124+
* `ssh_user` - (Computed/Sensitive) The user to connect to the node (string).
125+
* `system_info` - (Computed) General information about the node, such as kernel version, kubelet and kube-proxy version, Docker version (if used), and OS name.
126+
127+
### `system_info`
128+
129+
* `container_runtime_version` - (Computed) ContainerRuntime Version reported by the node through runtime remote API (e.g. docker://1.5.0).
130+
* `kernel_version` - (Computed) Kernel Version reported by the node from 'uname -r' (e.g. 3.16.0-0.bpo.4-amd64).
131+
* `kube_proxy_version` - (Computed) KubeProxy Version reported by the node.
132+
* `kubelet_version` - (Computed) Kubelet Version reported by the node.
133+
* `operating_system` - (Computed) The Operating System reported by the node.
134+
103135
## Timeouts
104136

105137
`rancher2_cluster_sync` provides the following

rancher2/config.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,27 @@ func (c *Config) GetClusterSpecialProjectsID(id string) (string, string, error)
596596
return defaultProjectID, systemProjectID, nil
597597
}
598598

599+
func (c *Config) GetClusterNodes(id string) ([]managementClient.Node, error) {
600+
if id == "" {
601+
return nil, fmt.Errorf("[ERROR] Cluster id is nil")
602+
}
603+
604+
client, err := c.ManagementClient()
605+
if err != nil {
606+
return nil, err
607+
}
608+
609+
filters := map[string]interface{}{"clusterId": id}
610+
listOpts := NewListOpts(filters)
611+
612+
collection, err := client.Node.List(listOpts)
613+
if err != nil {
614+
return nil, err
615+
}
616+
617+
return collection.Data, nil
618+
}
619+
599620
func (c *Config) GetClusterByName(name string) (*managementClient.Cluster, error) {
600621
if name == "" {
601622
return nil, fmt.Errorf("[ERROR] Cluster name is nil")

rancher2/resource_rancher2_cluster_sync.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ func resourceRancher2ClusterSyncRead(d *schema.ResourceData, meta interface{}) e
112112
return err
113113
}
114114
d.Set("kube_config", kubeConfig.Config)
115+
nodes, err := meta.(*Config).GetClusterNodes(clusterID)
116+
if err != nil {
117+
return err
118+
}
119+
d.Set("nodes", flattenClusterNodes(nodes))
115120
}
116121

117122
d.Set("synced", active)

rancher2/schema_cluster_sync.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ func clusterSyncFields() map[string]*schema.Schema {
3636
Type: schema.TypeString,
3737
},
3838
},
39+
"nodes": {
40+
Type: schema.TypeList,
41+
Computed: true,
42+
Elem: &schema.Resource{
43+
Schema: clusterNodeFields(),
44+
},
45+
},
3946
"synced": {
4047
Type: schema.TypeBool,
4148
Optional: true,
@@ -58,3 +65,75 @@ func clusterSyncFields() map[string]*schema.Schema {
5865

5966
return s
6067
}
68+
69+
func clusterNodeFields() map[string]*schema.Schema {
70+
s := map[string]*schema.Schema{
71+
72+
"capacity": {
73+
Type: schema.TypeMap,
74+
Computed: true,
75+
},
76+
"cluster_id": {
77+
Type: schema.TypeString,
78+
Computed: true,
79+
},
80+
"external_ip_address": {
81+
Type: schema.TypeString,
82+
Computed: true,
83+
},
84+
"hostname": {
85+
Type: schema.TypeString,
86+
Computed: true,
87+
},
88+
"id": {
89+
Type: schema.TypeString,
90+
Computed: true,
91+
},
92+
"ip_address": {
93+
Type: schema.TypeString,
94+
Computed: true,
95+
},
96+
"name": {
97+
Type: schema.TypeString,
98+
Computed: true,
99+
},
100+
"node_pool_id": {
101+
Type: schema.TypeString,
102+
Computed: true,
103+
},
104+
"node_template_id": {
105+
Type: schema.TypeString,
106+
Computed: true,
107+
},
108+
"provider_id": {
109+
Type: schema.TypeString,
110+
Computed: true,
111+
},
112+
"requested_hostname": {
113+
Type: schema.TypeString,
114+
Computed: true,
115+
},
116+
"roles": {
117+
Type: schema.TypeList,
118+
Computed: true,
119+
Elem: &schema.Schema{
120+
Type: schema.TypeString,
121+
},
122+
},
123+
"ssh_user": {
124+
Type: schema.TypeString,
125+
Computed: true,
126+
Sensitive: true,
127+
},
128+
"system_info": {
129+
Type: schema.TypeMap,
130+
Computed: true,
131+
},
132+
}
133+
134+
for k, v := range commonAnnotationLabelFields() {
135+
s[k] = v
136+
}
137+
138+
return s
139+
}

rancher2/structure_cluster.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,64 @@ func readPreservedClusterTemplateAnswers(d *schema.ResourceData) map[string]stri
254254
return preservedAnswers
255255
}
256256

257+
func flattenClusterNodes(in []managementClient.Node) []interface{} {
258+
if len(in) == 0 {
259+
return []interface{}{}
260+
}
261+
out := make([]interface{}, len(in))
262+
for i, in := range in {
263+
obj := make(map[string]interface{})
264+
265+
obj["annotations"] = toMapInterface(in.Annotations)
266+
obj["capacity"] = toMapInterface(in.Capacity)
267+
obj["cluster_id"] = in.ClusterID
268+
obj["external_ip_address"] = in.ExternalIPAddress
269+
obj["hostname"] = in.Hostname
270+
obj["id"] = in.ID
271+
obj["ip_address"] = in.IPAddress
272+
obj["labels"] = toMapInterface(in.Labels)
273+
obj["name"] = in.NodeName
274+
obj["node_pool_id"] = in.NodePoolID
275+
obj["node_template_id"] = in.NodeTemplateID
276+
obj["provider_id"] = in.ProviderId
277+
obj["requested_hostname"] = in.RequestedHostname
278+
obj["ssh_user"] = in.SshUser
279+
obj["system_info"] = flattenNodeInfo(in.Info)
280+
281+
var roles []string
282+
if in.ControlPlane {
283+
roles = append(roles, "control_plane")
284+
}
285+
if in.Etcd {
286+
roles = append(roles, "etcd")
287+
}
288+
if in.Worker {
289+
roles = append(roles, "worker")
290+
}
291+
obj["roles"] = roles
292+
293+
out[i] = obj
294+
}
295+
296+
return out
297+
}
298+
299+
func flattenNodeInfo(in *managementClient.NodeInfo) map[string]string {
300+
out := make(map[string]string)
301+
302+
if in == nil {
303+
return map[string]string{}
304+
}
305+
306+
out["kube_proxy_version"] = in.Kubernetes.KubeProxyVersion
307+
out["kubelet_version"] = in.Kubernetes.KubeletVersion
308+
out["container_runtime_version"] = in.OS.DockerVersion
309+
out["kernel_version"] = in.OS.KernelVersion
310+
out["operating_system"] = in.OS.OperatingSystem
311+
312+
return out
313+
}
314+
257315
// Expanders
258316

259317
func expandClusterRegistationToken(p []interface{}, clusterID string) (*managementClient.ClusterRegistrationToken, error) {

rancher2/structure_cluster_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
8+
"github.com/rancher/norman/types"
89
managementClient "github.com/rancher/rancher/pkg/client/generated/management/v3"
910
)
1011

@@ -650,3 +651,114 @@ func TestReadPreservedClusterTemplateAnswers(t *testing.T) {
650651
expectedOutput, result)
651652
}
652653
}
654+
655+
func TestFlattenClusterNodes(t *testing.T) {
656+
657+
testClusterNodes := []managementClient.Node{
658+
{
659+
Resource: types.Resource{
660+
ID: "id",
661+
},
662+
Annotations: map[string]string{
663+
"node_one": "one",
664+
"node_two": "two",
665+
},
666+
ClusterID: "cluster_id",
667+
Capacity: map[string]string{
668+
"cpu": "4",
669+
"memory": "8156056Ki",
670+
"pods": "110",
671+
},
672+
ControlPlane: true,
673+
Etcd: true,
674+
ExternalIPAddress: "172.18.0.5",
675+
Hostname: "hostname",
676+
IPAddress: "172.18.0.5",
677+
Info: &managementClient.NodeInfo{
678+
CPU: &managementClient.CPUInfo{
679+
Count: 4,
680+
},
681+
Kubernetes: &managementClient.KubernetesInfo{
682+
KubeProxyVersion: "v1.19.7",
683+
KubeletVersion: "v1.19.7",
684+
},
685+
Memory: &managementClient.MemoryInfo{
686+
MemTotalKiB: 8156056,
687+
},
688+
OS: &managementClient.OSInfo{
689+
DockerVersion: "containerd://1.4.3",
690+
KernelVersion: "4.19.121",
691+
OperatingSystem: "Unknown",
692+
},
693+
},
694+
Labels: map[string]string{
695+
"option1": "value1",
696+
"option2": "value2",
697+
},
698+
Name: "name",
699+
NodeName: "node_name",
700+
NodePoolID: "node_pool_id",
701+
NodeTemplateID: "node_template_id",
702+
ProviderId: "provider_id",
703+
RequestedHostname: "requested_hostname",
704+
SshUser: "ssh_user",
705+
Worker: true,
706+
},
707+
}
708+
709+
testClusterNodesInterface := []interface{}{
710+
map[string]interface{}{
711+
"id": "id",
712+
"annotations": map[string]interface{}{
713+
"node_one": "one",
714+
"node_two": "two",
715+
},
716+
"capacity": map[string]interface{}{
717+
"cpu": "4",
718+
"memory": "8156056Ki",
719+
"pods": "110",
720+
},
721+
"cluster_id": "cluster_id",
722+
"external_ip_address": "172.18.0.5",
723+
"hostname": "hostname",
724+
"ip_address": "172.18.0.5",
725+
"system_info": map[string]string{
726+
"kube_proxy_version": "v1.19.7",
727+
"kubelet_version": "v1.19.7",
728+
"container_runtime_version": "containerd://1.4.3",
729+
"kernel_version": "4.19.121",
730+
"operating_system": "Unknown",
731+
},
732+
"labels": map[string]interface{}{
733+
"option1": "value1",
734+
"option2": "value2",
735+
},
736+
"name": "node_name",
737+
"node_pool_id": "node_pool_id",
738+
"node_template_id": "node_template_id",
739+
"provider_id": "provider_id",
740+
"roles": []string{"control_plane", "etcd", "worker"},
741+
"requested_hostname": "requested_hostname",
742+
"ssh_user": "ssh_user",
743+
},
744+
}
745+
746+
cases := []struct {
747+
Input []managementClient.Node
748+
ExpectedOutput []interface{}
749+
}{
750+
{
751+
Input: testClusterNodes,
752+
ExpectedOutput: testClusterNodesInterface,
753+
},
754+
}
755+
756+
for _, tc := range cases {
757+
output := flattenClusterNodes(tc.Input)
758+
if !reflect.DeepEqual(output, tc.ExpectedOutput) {
759+
t.Fatalf("Unexpected output from flattener.\nExpected: %#v\nGiven: %#v",
760+
tc.ExpectedOutput, output)
761+
}
762+
}
763+
764+
}

0 commit comments

Comments
 (0)