Skip to content

Commit 6f39677

Browse files
author
Anna Blendermann
authored
Merge pull request #920 from annablender/k3s-rke2-etcd-snapshot-restore
Add k3s/rke2 etcd snapshot restore support
2 parents 3f19e39 + 502270a commit 6f39677

11 files changed

Lines changed: 317 additions & 1 deletion

docs/resources/cluster_v2.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,9 @@ The following attributes are exported:
420420
* `machine_selector_config` - (Optional/Computed) Cluster V2 machine selector config (list)
421421
* `registries` - (Optional) Cluster V2 docker registries (list maxitems:1)
422422
* `etcd` - (Optional) Cluster V2 etcd (list maxitems:1)
423+
* `rotate_certificates` (Optional) Cluster V2 certificate rotation (list maxitems:1)
424+
* `etcd_snapshot_create` (Optional) Cluster V2 etcd snapshot create (list maxitems:1)
425+
* `etcd_snapshot_restore` (Optional) Cluster V2 etcd snapshot restore (list maxitems:1)
423426

424427
#### `local_auth_endpoint`
425428

@@ -563,6 +566,27 @@ The following attributes are exported:
563566
* `region` - (Optional) ETCD snapshot S3 region (string)
564567
* `skip_ssl_verify` - (Optional) Disable ETCD skip ssl verify. Default: `false` (bool)
565568

569+
##### `rotate_certificates`
570+
571+
###### Arguments
572+
573+
* `generation` - (Required) Desired certificate rotation generation (int)
574+
* `services` - (Optional) Service certificates to rotate with this generation (string)
575+
576+
##### `etcd_snapshot_create`
577+
578+
###### Arguments
579+
580+
* `generation` - (Required) ETCD generation to initiate a snapshot (int)
581+
582+
##### `etcd_snapshot_restore`
583+
584+
###### Arguments
585+
586+
* `name` - (Required) ETCD snapshot name to restore (string)
587+
* `generation` (Required) ETCD snapshot desired generation (int)
588+
* `restore_rke_config` (Optional) ETCD restore RKE config (set to none, all, or kubernetesVersion) (string)
589+
566590
### `cluster_registration_token`
567591

568592
#### Attributes

rancher2/schema_cluster_v2_rke_config.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,24 @@ func clusterV2RKEConfigFields() map[string]*schema.Schema {
131131
Schema: clusterV2RKEConfigRotateCertificatesFields(),
132132
},
133133
},
134+
"etcd_snapshot_create": {
135+
Type: schema.TypeList,
136+
MaxItems: 1,
137+
Optional: true,
138+
Description: "Cluster V2 etcd snapshot create",
139+
Elem: &schema.Resource{
140+
Schema: clusterV2RKEConfigETCDSnapshotCreateFields(),
141+
},
142+
},
143+
"etcd_snapshot_restore": {
144+
Type: schema.TypeList,
145+
MaxItems: 1,
146+
Optional: true,
147+
Description: "Cluster V2 etcd snapshot restore",
148+
Elem: &schema.Resource{
149+
Schema: clusterV2RKEConfigETCDSnapshotRestoreFields(),
150+
},
151+
},
134152
}
135153

136154
return s

rancher2/schema_cluster_v2_rke_config_certificate_rotation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ func clusterV2RKEConfigRotateCertificatesFields() map[string]*schema.Schema {
1010
s := map[string]*schema.Schema{
1111
"generation": {
1212
Type: schema.TypeInt,
13-
Optional: true,
13+
Required: true,
1414
Description: "Desired certificate rotation generation.",
1515
},
1616
"services": {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package rancher2
2+
3+
import "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
4+
5+
//Types
6+
7+
func clusterV2RKEConfigETCDSnapshotCreateFields() map[string]*schema.Schema {
8+
s := map[string]*schema.Schema{
9+
"generation": {
10+
Type: schema.TypeInt,
11+
Required: true,
12+
Description: "ETCD generation to initiate a snapshot",
13+
},
14+
}
15+
16+
return s
17+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package rancher2
2+
3+
import "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
4+
5+
//Types
6+
7+
func clusterV2RKEConfigETCDSnapshotRestoreFields() map[string]*schema.Schema {
8+
s := map[string]*schema.Schema{
9+
"name": {
10+
Type: schema.TypeString,
11+
Required: true,
12+
Description: "ETCD snapshot name to restore",
13+
},
14+
"generation": {
15+
Type: schema.TypeInt,
16+
Required: true,
17+
Description: "ETCD snapshot desired generation",
18+
},
19+
"restore_rke_config": {
20+
Type: schema.TypeString,
21+
Optional: true,
22+
Description: "ETCD restore RKE config (set to none, all, or kubernetesVersion)",
23+
},
24+
}
25+
26+
return s
27+
}

rancher2/structure_cluster_v2_rke_config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ func flattenClusterV2RKEConfig(in *provisionv1.RKEConfig) []interface{} {
4343
if in.RotateCertificates != nil {
4444
obj["rotate_certificates"] = flattenClusterV2RKEConfigRotateCertificates(in.RotateCertificates)
4545
}
46+
if in.ETCDSnapshotCreate != nil {
47+
obj["etcd_snapshot_create"] = flattenClusterV2RKEConfigETCDSnapshotCreate(in.ETCDSnapshotCreate)
48+
}
49+
if in.ETCDSnapshotRestore != nil {
50+
obj["etcd_snapshot_restore"] = flattenClusterV2RKEConfigETCDSnapshotRestore(in.ETCDSnapshotRestore)
51+
}
4652

4753
return []interface{}{obj}
4854
}
@@ -89,6 +95,12 @@ func expandClusterV2RKEConfig(p []interface{}) *provisionv1.RKEConfig {
8995
if v, ok := in["rotate_certificates"].([]interface{}); ok && len(v) > 0 {
9096
obj.RotateCertificates = expandClusterV2RKEConfigRotateCertificates(v)
9197
}
98+
if v, ok := in["etcd_snapshot_create"].([]interface{}); ok && len(v) > 0 {
99+
obj.ETCDSnapshotCreate = expandClusterV2RKEConfigETCDSnapshotCreate(v)
100+
}
101+
if v, ok := in["etcd_snapshot_restore"].([]interface{}); ok && len(v) > 0 {
102+
obj.ETCDSnapshotRestore = expandClusterV2RKEConfigETCDSnapshotRestore(v)
103+
}
92104

93105
return obj
94106
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package rancher2
2+
3+
import rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
4+
5+
func flattenClusterV2RKEConfigETCDSnapshotCreate(in *rkev1.ETCDSnapshotCreate) []interface{} {
6+
if in == nil {
7+
return nil
8+
}
9+
10+
obj := make(map[string]interface{})
11+
12+
if in.Generation > 0 {
13+
obj["generation"] = in.Generation
14+
}
15+
16+
return []interface{}{obj}
17+
}
18+
19+
func expandClusterV2RKEConfigETCDSnapshotCreate(p []interface{}) *rkev1.ETCDSnapshotCreate {
20+
if p == nil || len(p) == 0 || p[0] == nil {
21+
return nil
22+
}
23+
24+
obj := &rkev1.ETCDSnapshotCreate{}
25+
26+
in := p[0].(map[string]interface{})
27+
28+
if v, ok := in["generation"].(int); ok && v > 0 {
29+
obj.Generation = v
30+
}
31+
32+
return obj
33+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package rancher2
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
8+
)
9+
10+
var (
11+
testClusterV2RKEConfigETCDSnapshotCreateConf *rkev1.ETCDSnapshotCreate
12+
testClusterV2RKEConfigETCDSnapshotCreateInterface []interface{}
13+
)
14+
15+
func init() {
16+
testClusterV2RKEConfigETCDSnapshotCreateConf = &rkev1.ETCDSnapshotCreate{
17+
Generation: 1,
18+
}
19+
20+
testClusterV2RKEConfigETCDSnapshotCreateInterface = []interface{}{
21+
map[string]interface{}{
22+
"generation": 1,
23+
},
24+
}
25+
}
26+
27+
func TestFlattenClusterV2RKEConfigETCDSnapshotCreate(t *testing.T) {
28+
cases := []struct {
29+
Input *rkev1.ETCDSnapshotCreate
30+
ExpectedOutput []interface{}
31+
}{
32+
{
33+
testClusterV2RKEConfigETCDSnapshotCreateConf,
34+
testClusterV2RKEConfigETCDSnapshotCreateInterface,
35+
},
36+
}
37+
38+
for _, tc := range cases {
39+
output := flattenClusterV2RKEConfigETCDSnapshotCreate(tc.Input)
40+
if !reflect.DeepEqual(output, tc.ExpectedOutput) {
41+
t.Fatalf("Unexpected output from flattener.\nExpected: %#v\nGiven: %#v",
42+
tc.ExpectedOutput, output)
43+
}
44+
}
45+
}
46+
47+
func TestExpandClusterV2RKEConfigETCDSnapshotCreate(t *testing.T) {
48+
49+
cases := []struct {
50+
Input []interface{}
51+
ExpectedOutput *rkev1.ETCDSnapshotCreate
52+
}{
53+
{
54+
testClusterV2RKEConfigETCDSnapshotCreateInterface,
55+
testClusterV2RKEConfigETCDSnapshotCreateConf,
56+
},
57+
}
58+
59+
for _, tc := range cases {
60+
output := expandClusterV2RKEConfigETCDSnapshotCreate(tc.Input)
61+
if !reflect.DeepEqual(output, tc.ExpectedOutput) {
62+
t.Fatalf("Unexpected output from expander.\nExpected: %#v\nGiven: %#v",
63+
tc.ExpectedOutput, output)
64+
}
65+
}
66+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package rancher2
2+
3+
import rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
4+
5+
func flattenClusterV2RKEConfigETCDSnapshotRestore(in *rkev1.ETCDSnapshotRestore) []interface{} {
6+
if in == nil {
7+
return nil
8+
}
9+
10+
obj := make(map[string]interface{})
11+
12+
if len(in.Name) > 0 {
13+
obj["name"] = in.Name
14+
}
15+
if in.Generation > 0 {
16+
obj["generation"] = in.Generation
17+
}
18+
if len(in.RestoreRKEConfig) > 0 {
19+
obj["restore_rke_config"] = in.RestoreRKEConfig
20+
}
21+
22+
return []interface{}{obj}
23+
}
24+
25+
func expandClusterV2RKEConfigETCDSnapshotRestore(p []interface{}) *rkev1.ETCDSnapshotRestore {
26+
if p == nil || len(p) == 0 || p[0] == nil {
27+
return nil
28+
}
29+
30+
obj := &rkev1.ETCDSnapshotRestore{}
31+
32+
in := p[0].(map[string]interface{})
33+
34+
if v, ok := in["name"].(string); ok && len(v) > 0 {
35+
obj.Name = v
36+
}
37+
if v, ok := in["generation"].(int); ok && v > 0 {
38+
obj.Generation = v
39+
}
40+
if v, ok := in["restore_rke_config"].(string); ok && len(v) > 0 {
41+
obj.RestoreRKEConfig = v
42+
}
43+
44+
return obj
45+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package rancher2
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
8+
)
9+
10+
var (
11+
testClusterV2RKEConfigETCDSnapshotRestoreConf *rkev1.ETCDSnapshotRestore
12+
testClusterV2RKEConfigETCDSnapshotRestoreInterface []interface{}
13+
)
14+
15+
func init() {
16+
testClusterV2RKEConfigETCDSnapshotRestoreConf = &rkev1.ETCDSnapshotRestore{
17+
Name: "SnapshotTestName",
18+
Generation: 1,
19+
RestoreRKEConfig: "all",
20+
}
21+
22+
testClusterV2RKEConfigETCDSnapshotRestoreInterface = []interface{}{
23+
map[string]interface{}{
24+
"name": "SnapshotTestName",
25+
"generation": 1,
26+
"restore_rke_config": "all",
27+
},
28+
}
29+
}
30+
31+
func TestFlattenClusterV2RKEConfigETCDSnapshotRestore(t *testing.T) {
32+
cases := []struct {
33+
Input *rkev1.ETCDSnapshotRestore
34+
ExpectedOutput []interface{}
35+
}{
36+
{
37+
testClusterV2RKEConfigETCDSnapshotRestoreConf,
38+
testClusterV2RKEConfigETCDSnapshotRestoreInterface,
39+
},
40+
}
41+
42+
for _, tc := range cases {
43+
output := flattenClusterV2RKEConfigETCDSnapshotRestore(tc.Input)
44+
if !reflect.DeepEqual(output, tc.ExpectedOutput) {
45+
t.Fatalf("Unexpected output from flattener.\nExpected: %#v\nGiven: %#v",
46+
tc.ExpectedOutput, output)
47+
}
48+
}
49+
}
50+
51+
func TestExpandClusterV2RKEConfigETCDSnapshotRestore(t *testing.T) {
52+
53+
cases := []struct {
54+
Input []interface{}
55+
ExpectedOutput *rkev1.ETCDSnapshotRestore
56+
}{
57+
{
58+
testClusterV2RKEConfigETCDSnapshotRestoreInterface,
59+
testClusterV2RKEConfigETCDSnapshotRestoreConf,
60+
},
61+
}
62+
63+
for _, tc := range cases {
64+
output := expandClusterV2RKEConfigETCDSnapshotRestore(tc.Input)
65+
if !reflect.DeepEqual(output, tc.ExpectedOutput) {
66+
t.Fatalf("Unexpected output from expander.\nExpected: %#v\nGiven: %#v",
67+
tc.ExpectedOutput, output)
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)