Skip to content

Commit

Permalink
Add file assets to node user data scripts, fingerprint fileAssets and…
Browse files Browse the repository at this point in the history
… hooks content.
  • Loading branch information
KashifSaadat committed Aug 31, 2017
1 parent 2fd0ddb commit 4693731
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 140 deletions.
69 changes: 67 additions & 2 deletions pkg/model/bootstrapscript.go
Expand Up @@ -18,6 +18,8 @@ package model

import (
"bytes"
"crypto/sha1"
"encoding/base64"
"fmt"
"os"
"strconv"
Expand Down Expand Up @@ -107,7 +109,20 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, cs *kops.Cluste

hooks := b.getRelevantHooks(cs.Hooks, ig.Spec.Role)
if len(hooks) > 0 {
spec["hooks"] = hooks
if hooksFingerprint, err := b.fingerprintSpecList(hooks); err != nil {
return "", err
} else {
spec["hooksFingerprint"] = hooksFingerprint
}
}

fileAssets := b.getRelevantFileAssets(cs.FileAssets, ig.Spec.Role)
if len(fileAssets) > 0 {
if fileAssetsFingerprint, err := b.fingerprintSpecList(fileAssets); err != nil {
return "", err
} else {
spec["fileAssetsFingerprint"] = fileAssetsFingerprint
}
}

content, err := yaml.Marshal(spec)
Expand All @@ -124,7 +139,19 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, cs *kops.Cluste
spec["taints"] = ig.Spec.Taints
hooks := b.getRelevantHooks(ig.Spec.Hooks, ig.Spec.Role)
if len(hooks) > 0 {
spec["hooks"] = hooks
if hooksFingerprint, err := b.fingerprintSpecList(hooks); err != nil {
return "", err
} else {
spec["hooksFingerprint"] = hooksFingerprint
}
}
fileAssets := b.getRelevantFileAssets(ig.Spec.FileAssets, ig.Spec.Role)
if len(fileAssets) > 0 {
if fileAssetsFingerprint, err := b.fingerprintSpecList(fileAssets); err != nil {
return "", err
} else {
spec["fileAssetsFingerprint"] = fileAssetsFingerprint
}
}

content, err := yaml.Marshal(spec)
Expand All @@ -146,6 +173,7 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, cs *kops.Cluste
// getRelevantHooks returns a list of hooks to be applied to the instance group
func (b *BootstrapScript) getRelevantHooks(hooks []kops.HookSpec, role kops.InstanceGroupRole) []kops.HookSpec {
relevantHooks := []kops.HookSpec{}

for _, hook := range hooks {
if len(hook.Roles) == 0 {
relevantHooks = append(relevantHooks, hook)
Expand All @@ -158,9 +186,46 @@ func (b *BootstrapScript) getRelevantHooks(hooks []kops.HookSpec, role kops.Inst
}
}
}

return relevantHooks
}

// getRelevantFileAssets returns a list of file assets to be applied to the instance group
func (b *BootstrapScript) getRelevantFileAssets(fileAssets []kops.FileAssetSpec, role kops.InstanceGroupRole) []kops.FileAssetSpec {
relevantFileAssets := []kops.FileAssetSpec{}

for _, fileAsset := range fileAssets {
if len(fileAsset.Roles) == 0 {
relevantFileAssets = append(relevantFileAssets, fileAsset)
continue
}
for _, fileAssetRole := range fileAsset.Roles {
if role == fileAssetRole {
relevantFileAssets = append(relevantFileAssets, fileAsset)
break
}
}
}

return relevantFileAssets
}

// fingerprintSpecList takes a list of objects and returns a base64 encoded fingerprint
func (b *BootstrapScript) fingerprintSpecList(spec interface{}) (string, error) {
hasher := sha1.New()

data, err := kops.ToRawYaml(spec)
if err != nil {
return "", err
}

if _, err := hasher.Write(data); err != nil {
return "", fmt.Errorf("error computing fingerprint hash: %v", err)
}

return base64.StdEncoding.EncodeToString(hasher.Sum(nil)), nil
}

func (b *BootstrapScript) createProxyEnv(ps *kops.EgressProxySpec) string {
var buffer bytes.Buffer

Expand Down
94 changes: 62 additions & 32 deletions pkg/model/bootstrapscript_test.go
Expand Up @@ -55,55 +55,64 @@ func Test_ProxyFunc(t *testing.T) {

func TestBootstrapUserData(t *testing.T) {
cs := []struct {
Role kops.InstanceGroupRole
ExpectedFilePath string
HookSpecRoles []kops.InstanceGroupRole
Role kops.InstanceGroupRole
ExpectedFilePath string
HookSpecRoles []kops.InstanceGroupRole
FileAssetSpecRoles []kops.InstanceGroupRole
}{
{
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_0.txt",
HookSpecRoles: []kops.InstanceGroupRole{""},
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_0.txt",
HookSpecRoles: []kops.InstanceGroupRole{""},
FileAssetSpecRoles: []kops.InstanceGroupRole{""},
},
{
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_0.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Node"},
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_0.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Node"},
FileAssetSpecRoles: []kops.InstanceGroupRole{"Node"},
},
{
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_1.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master"},
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_1.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master"},
FileAssetSpecRoles: []kops.InstanceGroupRole{"Master"},
},
{
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_2.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master", "Node"},
Role: "Master",
ExpectedFilePath: "tests/data/bootstrapscript_2.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master", "Node"},
FileAssetSpecRoles: []kops.InstanceGroupRole{"Master", "Node"},
},
{
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_3.txt",
HookSpecRoles: []kops.InstanceGroupRole{""},
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_3.txt",
HookSpecRoles: []kops.InstanceGroupRole{""},
FileAssetSpecRoles: []kops.InstanceGroupRole{""},
},
{
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_4.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Node"},
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_4.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Node"},
FileAssetSpecRoles: []kops.InstanceGroupRole{"Node"},
},
{
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_3.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master"},
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_3.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master"},
FileAssetSpecRoles: []kops.InstanceGroupRole{"Master"},
},
{
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_5.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master", "Node"},
Role: "Node",
ExpectedFilePath: "tests/data/bootstrapscript_5.txt",
HookSpecRoles: []kops.InstanceGroupRole{"Master", "Node"},
FileAssetSpecRoles: []kops.InstanceGroupRole{"Master", "Node"},
},
}

for i, x := range cs {
spec := makeTestCluster(x.HookSpecRoles).Spec
group := makeTestInstanceGroup(x.Role, x.HookSpecRoles)
spec := makeTestCluster(x.HookSpecRoles, x.FileAssetSpecRoles).Spec
group := makeTestInstanceGroup(x.Role, x.HookSpecRoles, x.FileAssetSpecRoles)

renderNodeUpConfig := func(ig *kops.InstanceGroup) (*nodeup.Config, error) {
return &nodeup.Config{}, nil
Expand Down Expand Up @@ -134,13 +143,13 @@ func TestBootstrapUserData(t *testing.T) {

if actual != string(expectedBytes) {
diffString := diff.FormatDiff(string(expectedBytes), actual)
t.Errorf("case %d failed, actual output differed from expected.", i)
t.Errorf("case %d failed, actual output differed from expected (%s).", i, x.ExpectedFilePath)
t.Logf("diff:\n%s\n", diffString)
}
}
}

func makeTestCluster(hookSpecRoles []kops.InstanceGroupRole) *kops.Cluster {
func makeTestCluster(hookSpecRoles []kops.InstanceGroupRole, fileAssetSpecRoles []kops.InstanceGroupRole) *kops.Cluster {
return &kops.Cluster{
Spec: kops.ClusterSpec{
CloudProvider: "aws",
Expand Down Expand Up @@ -207,11 +216,19 @@ func makeTestCluster(hookSpecRoles []kops.InstanceGroupRole) *kops.Cluster {
Roles: hookSpecRoles,
},
},
FileAssets: []kops.FileAssetSpec{
{
Name: "iptables-restore",
Path: "/var/lib/iptables/rules-save",
Content: "blah blah",
Roles: fileAssetSpecRoles,
},
},
},
}
}

func makeTestInstanceGroup(role kops.InstanceGroupRole, hookSpecRoles []kops.InstanceGroupRole) *kops.InstanceGroup {
func makeTestInstanceGroup(role kops.InstanceGroupRole, hookSpecRoles []kops.InstanceGroupRole, fileAssetSpecRoles []kops.InstanceGroupRole) *kops.InstanceGroup {
return &kops.InstanceGroup{
Spec: kops.InstanceGroupSpec{
Kubelet: &kops.KubeletConfigSpec{
Expand Down Expand Up @@ -240,6 +257,19 @@ func makeTestInstanceGroup(role kops.InstanceGroupRole, hookSpecRoles []kops.Ins
Manifest: "Type=oneshot\nExecStart=/usr/bin/systemctl start apply-to-all.service",
},
},
FileAssets: []kops.FileAssetSpec{
{
Name: "iptables-restore",
Path: "/var/lib/iptables/rules-save",
Content: "blah blah",
Roles: fileAssetSpecRoles,
},
{
Name: "tokens",
Path: "/kube/tokens.csv",
Content: "user,token",
},
},
},
}
}
7 changes: 2 additions & 5 deletions pkg/model/tests/data/bootstrapscript_0.txt
Expand Up @@ -167,11 +167,8 @@ masterKubelet:
__EOF_CLUSTER_SPEC

cat > ig_spec.yaml << '__EOF_IG_SPEC'
hooks:
- manifest: |-
Type=oneshot
ExecStart=/usr/bin/systemctl start apply-to-all.service
name: apply-to-all.service
fileAssetsFingerprint: f6kSdymj6QC/kaTXf378EkOVrxk=
hooksFingerprint: xfN3/XfStdhokilj/u/nXIe163g=
kubelet:
kubeconfigPath: /etc/kubernetes/igconfig.txt
nodeLabels:
Expand Down
27 changes: 4 additions & 23 deletions pkg/model/tests/data/bootstrapscript_1.txt
Expand Up @@ -149,15 +149,8 @@ cloudConfig:
nodeTags: something
docker:
logLevel: INFO
hooks:
- execContainer:
command:
- sh
- -c
- chroot /rootfs apt-get update && chroot /rootfs apt-get install -y ceph-common
image: busybox
roles:
- Master
fileAssetsFingerprint: UYwmqzs8EUbuejmlWbrml0HeXyw=
hooksFingerprint: i5Oll1wrZylTnUAkZWtaVxzoShc=
kubeAPIServer:
image: CoreOS
kubeControllerManager:
Expand All @@ -176,20 +169,8 @@ masterKubelet:
__EOF_CLUSTER_SPEC

cat > ig_spec.yaml << '__EOF_IG_SPEC'
hooks:
- before:
- update-engine.service
- kubelet.service
manifest: |-
Type=oneshot
ExecStart=/usr/bin/systemctl stop update-engine.service
name: disable-update-engine.service
roles:
- Master
- manifest: |-
Type=oneshot
ExecStart=/usr/bin/systemctl start apply-to-all.service
name: apply-to-all.service
fileAssetsFingerprint: R6pJpxsF/R+aBwl6qokrzrgjaLI=
hooksFingerprint: kNrhmJbq15bogZszFmSoDmvXQzE=
kubelet:
kubeconfigPath: /etc/kubernetes/igconfig.txt
nodeLabels:
Expand Down
29 changes: 4 additions & 25 deletions pkg/model/tests/data/bootstrapscript_2.txt
Expand Up @@ -149,16 +149,8 @@ cloudConfig:
nodeTags: something
docker:
logLevel: INFO
hooks:
- execContainer:
command:
- sh
- -c
- chroot /rootfs apt-get update && chroot /rootfs apt-get install -y ceph-common
image: busybox
roles:
- Master
- Node
fileAssetsFingerprint: aeo7l/I9BNQM694w+/BQQ6xUrXU=
hooksFingerprint: ppDpzDQn7VC7l9rM8yOpFFBOWvE=
kubeAPIServer:
image: CoreOS
kubeControllerManager:
Expand All @@ -177,21 +169,8 @@ masterKubelet:
__EOF_CLUSTER_SPEC

cat > ig_spec.yaml << '__EOF_IG_SPEC'
hooks:
- before:
- update-engine.service
- kubelet.service
manifest: |-
Type=oneshot
ExecStart=/usr/bin/systemctl stop update-engine.service
name: disable-update-engine.service
roles:
- Master
- Node
- manifest: |-
Type=oneshot
ExecStart=/usr/bin/systemctl start apply-to-all.service
name: apply-to-all.service
fileAssetsFingerprint: ivoCIJMROq2UPZ7OWE8aREA+MAE=
hooksFingerprint: JfwleiB5ni//vuR458vnJjHkpzY=
kubelet:
kubeconfigPath: /etc/kubernetes/igconfig.txt
nodeLabels:
Expand Down
7 changes: 2 additions & 5 deletions pkg/model/tests/data/bootstrapscript_3.txt
Expand Up @@ -159,11 +159,8 @@ kubelet:
__EOF_CLUSTER_SPEC

cat > ig_spec.yaml << '__EOF_IG_SPEC'
hooks:
- manifest: |-
Type=oneshot
ExecStart=/usr/bin/systemctl start apply-to-all.service
name: apply-to-all.service
fileAssetsFingerprint: f6kSdymj6QC/kaTXf378EkOVrxk=
hooksFingerprint: xfN3/XfStdhokilj/u/nXIe163g=
kubelet:
kubeconfigPath: /etc/kubernetes/igconfig.txt
nodeLabels:
Expand Down

0 comments on commit 4693731

Please sign in to comment.