Repository: keikoproj/instance-manager
Pull request #248 (2021-02-11 04:42:48)

fix: remove whitespaces causing rolling upgrade
Signed-off-by: Eytan Avisror <eytan_avisror@intuit.com>

Some whitespaces were introduced in #216 that cause a rolling upgrade when controller is upgraded.
This PR removes the whitespaces to maintain same userData if spec did not change.

codecov[bot]: # [Codecov](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=h1) Report
> Merging [#248](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=desc) (8f752ef) into [master](https://codecov.io/gh/keikoproj/instance-manager/commit/8aab023fb4966cd5326e3cf12eefa51866defbef?el=desc) (8aab023) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/keikoproj/instance-manager/pull/248/graphs/tree.svg?width=650&height=150&src=pr&token=IJbjmSBliL)](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master     #248   +/-   ##
=======================================
  Coverage   88.10%   88.10%           
=======================================
  Files          17       17           
  Lines        2237     2237           
=======================================
  Hits         1971     1971           
  Misses        162      162           
  Partials      104      104           
```


| [Impacted Files](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [controllers/provisioners/eks/helpers.go](https://codecov.io/gh/keikoproj/instance-manager/pull/248/diff?src=pr&el=tree#diff-Y29udHJvbGxlcnMvcHJvdmlzaW9uZXJzL2Vrcy9oZWxwZXJzLmdv) | `91.15% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=footer). Last update [8aab023...453ded8](https://codecov.io/gh/keikoproj/instance-manager/pull/248?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/controllers/provisioners/eks/helpers.go b/controllers/provisioners/eks/helpers.go
index 631fbf1..e781d8c 100644
--- a/controllers/provisioners/eks/helpers.go
+++ b/controllers/provisioners/eks/helpers.go
@@ -497,7 +497,7 @@ func (ctx *EksInstanceGroupContext) GetBootstrapArgs() string {
 	if bootstrapOptions != nil && bootstrapOptions.MaxPods > 0 {
 		sb.WriteString("--use-max-pods false ")
 	}
-	sb.WriteString(fmt.Sprintf("--kubelet-extra-args '%v' ", ctx.GetKubeletExtraArgs()))
+	sb.WriteString(fmt.Sprintf("--kubelet-extra-args '%v'", ctx.GetKubeletExtraArgs()))
 	return sb.String()
 }
 
@@ -512,9 +512,9 @@ func (ctx *EksInstanceGroupContext) GetKubeletExtraArgs() string {
 	labelsFlag := fmt.Sprintf("--node-labels=%v", strings.Join(ctx.GetLabelList(), ","))
 	taintsFlag := fmt.Sprintf("--register-with-taints=%v", strings.Join(ctx.GetTaintList(), ","))
 	var sb strings.Builder
-	sb.WriteString(fmt.Sprintf("%v %v %v ", labelsFlag, taintsFlag, bootstrapArgs))
+	sb.WriteString(fmt.Sprintf("%v %v %v", labelsFlag, taintsFlag, bootstrapArgs))
 	if bootstrapOptions != nil && bootstrapOptions.MaxPods > 0 {
-		sb.WriteString(fmt.Sprintf("--max-pods=%v ", bootstrapOptions.MaxPods))
+		sb.WriteString(fmt.Sprintf(" --max-pods=%v", bootstrapOptions.MaxPods))
 	}
 	return sb.String()
 }


Test patch:
diff --git a/controllers/provisioners/eks/helpers_test.go b/controllers/provisioners/eks/helpers_test.go
index c98c279..f38c6c6 100644
--- a/controllers/provisioners/eks/helpers_test.go
+++ b/controllers/provisioners/eks/helpers_test.go
@@ -81,6 +81,82 @@ func TestAutoscalerTags(t *testing.T) {
 
 }
 
+func TestGetBasicUserDataAmazonLinux2(t *testing.T) {
+	var (
+		k             = MockKubernetesClientSet()
+		ig            = MockInstanceGroup()
+		asgMock       = NewAutoScalingMocker()
+		iamMock       = NewIamMocker()
+		eksMock       = NewEksMocker()
+		ec2Mock       = NewEc2Mocker()
+		configuration = ig.GetEKSConfiguration()
+	)
+
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
+	ctx := MockContext(ig, k, w)
+
+	configuration.BootstrapOptions = &v1alpha1.BootstrapOptions{
+		MaxPods: 4,
+	}
+	configuration.Labels = map[string]string{
+		"foo": "bar",
+	}
+	configuration.Taints = []corev1.Taint{
+		{
+			Key:    "foo",
+			Value:  "bar",
+			Effect: "NoSchedule",
+		},
+	}
+	persistance := true
+	configuration.Volumes = []v1alpha1.NodeVolume{
+		{
+			Name: "/dev/xvda",
+			Type: "gp2",
+			MountOptions: &v1alpha1.NodeVolumeMountOptions{
+				FileSystem:  "xfs",
+				Mount:       "/mnt/foo",
+				Persistance: &persistance,
+			},
+		},
+	}
+	configuration.BootstrapArguments = "--eviction-hard=memory.available<300Mi,nodefs.available<5% --system-reserved=memory=2.5Gi --v=2"
+	configuration.UserData = []v1alpha1.UserDataStage{
+		{
+			Stage: "PreBootstrap",
+			Data:  "foo",
+		},
+		{
+			Stage: "PostBootstrap",
+			Data:  "bar",
+		},
+	}
+	var (
+		args            = ctx.GetBootstrapArgs()
+		kubeletArgs     = ctx.GetKubeletExtraArgs()
+		userDataPayload = ctx.GetUserDataStages()
+		mounts          = ctx.GetMountOpts()
+	)
+
+	expectedData := `#!/bin/bash
+foo
+mkfs.xfs /dev/xvda
+mkdir /mnt/foo
+mount /dev/xvda /mnt/foo
+mount
+set -o xtrace
+/etc/eks/bootstrap.sh foo --use-max-pods false --kubelet-extra-args '--node-labels=foo=bar,node.kubernetes.io/role=instance-group-1 --register-with-taints=foo=bar:NoSchedule --eviction-hard=memory.available<300Mi,nodefs.available<5% --system-reserved=memory=2.5Gi --v=2 --max-pods=4'
+set +o xtrace
+bar`
+	userData := ctx.GetBasicUserData("foo", args, kubeletArgs, userDataPayload, mounts)
+	basicUserDataDecoded, _ := base64.StdEncoding.DecodeString(userData)
+	basicUserDataString := string(basicUserDataDecoded)
+	if basicUserDataString != expectedData {
+		t.Fatalf("\nExpected: START>%v<END\n Got: START>%v<END", expectedData, basicUserDataString)
+	}
+
+}
+
 func TestCustomNetworkingMaxPods(t *testing.T) {
 	var (
 		k       = MockKubernetesClientSet()