Skip to content

Commit

Permalink
Merge pull request #17 from 4ARMED/eks_refactor
Browse files Browse the repository at this point in the history
Tweaks to support EKS cloud-config changes
  • Loading branch information
marcwickenden authored Aug 8, 2022
2 parents bdc697d + a6f322a commit c026c5f
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 19 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ EXECUTABLE := "kubeletmein"
GITVERSION := $(shell git describe --dirty --always --tags --long)
PACKAGENAME := $(shell go list -m -f '{{.Path}}')

build: clean test
build: clean
go build -ldflags "-extldflags '-static' -X ${PACKAGENAME}/pkg/config.GitVersion=${GITVERSION}" -o ${EXECUTABLE} ./cmd/kubeletmein

build-quick: clean
go build -ldflags "-extldflags '-static' -X ${PACKAGENAME}/pkg/config.GitVersion=${GITVERSION}" -o ${EXECUTABLE} ./cmd/kubeletmein

build-linux:
GOOS=linux go build -ldflags "-extldflags '-static' -X ${PACKAGENAME}/pkg/config.GitVersion=${GITVERSION}" -o ${EXECUTABLE}-linux ./cmd/kubeletmein
GOOS=linux GOARCH=amd64 go build -ldflags "-extldflags '-static' -X ${PACKAGENAME}/pkg/config.GitVersion=${GITVERSION}" -o ${EXECUTABLE}-linux ./cmd/kubeletmein

clean:
@rm -f ${EXECUTABLE}
Expand Down
1 change: 1 addition & 0 deletions cmd/kubeletmein/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func Generate(c *config.Config) *cobra.Command {
cmd.Flags().StringVarP(&c.MetadataFile, "metadata-file", "f", "", "Don't try to parse metadata, load from the specified filename instead")
cmd.Flags().StringVarP(&c.CertDir, "cert-dir", "d", "kubeletmein-pki", "Directory into which the new cert will be written")
cmd.Flags().StringVarP(&c.NodeName, "node-name", "n", "", "Node name to use for CSR. Default is to detect from metadata if needed")
cmd.Flags().StringVar(&c.Region, "region", "", "Region used in generation of kubeconfig")

return cmd
}
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ type Config struct {
NodeName string
KubeAPIServer string
MetadataFile string
Region string
}
24 changes: 18 additions & 6 deletions pkg/eks/eks.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
// Generate creates the kubeconfig for EKS
func Generate(c *config.Config) error {
var userData string
var region string
var err error

// get user-data
Expand All @@ -46,9 +47,16 @@ func Generate(c *config.Config) error {
}
}

if c.Region != "" {
region, err = getRegion()
if err != nil {
return err
}
}

// These parsers should return an api.Config{} struct
logger.Info("parsing user-data")
kubeConfigData, err := ParseUserData(userData)
kubeConfigData, err := ParseUserData(userData, region)
if err != nil {
return err
}
Expand All @@ -65,13 +73,17 @@ func Generate(c *config.Config) error {
return err
}

// TODO: refactor all of this to be better mockable.
// At the moment we have these calls here which ignore the functions in
// metadata.go completely.
func getUserData() (string, error) {
md := ec2metadata.New(session.New())

userData, err := md.GetUserData()
if err != nil {
return "", err
}
return md.GetUserData()
}

func getRegion() (string, error) {
md := ec2metadata.New(session.New())

return userData, nil
return md.Region()
}
6 changes: 5 additions & 1 deletion pkg/eks/eks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"github.com/stretchr/testify/assert"
)

var (
region string = "eu-west-1"
)

func TestGetUserDataCloudConfig(t *testing.T) {
// Shell script

Expand All @@ -24,7 +28,7 @@ func TestParseUserDataFromFile(t *testing.T) {
t.Errorf("err: %v", err)
}

kubeConfigData, err := ParseUserData(userData)
kubeConfigData, err := ParseUserData(userData, region)
if err != nil {
t.Errorf("err: %v", err)
}
Expand Down
12 changes: 7 additions & 5 deletions pkg/eks/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ func NewEC2MetadataClient() (*EC2MetadataClient, error) {
// This is all so we can mock it. There has to be a better way but
// the AWS Go SDK seems...a bit rubbish.
func (c *EC2MetadataClient) GetUserData() (string, error) {
userData, err := c.GetUserData()
if err != nil {
return "", err
}
return c.GetUserData()
}

return userData, nil
// Region wraps the the AWS EC2 Region call
// This is all so we can mock it. There has to be a better way but
// the AWS Go SDK seems...a bit rubbish.
func (c *EC2MetadataClient) Region() (string, error) {
return c.Region()
}
Binary file added pkg/eks/testdata/cloud-config-two.txt.gz
Binary file not shown.
63 changes: 60 additions & 3 deletions pkg/eks/userdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type CloudConfig struct {

// ParseUserData takes a string input metadata, works out its type
// and returns a *clientcmdapi.Config ready for marshalling to disk.
func ParseUserData(userData string) (*clientcmdapi.Config, error) {
func ParseUserData(userData, region string) (*clientcmdapi.Config, error) {

var kubeConfigData *clientcmdapi.Config

Expand All @@ -55,7 +55,7 @@ func ParseUserData(userData string) (*clientcmdapi.Config, error) {
match := re.MatchString(userData)
if match {
logger.Debug("assuming gzipped cloud-config")
kubeConfigData, err = ParseCloudConfig([]byte(userData))
kubeConfigData, err = ParseCloudConfig([]byte(userData), region)
if err != nil {
return nil, err
}
Expand All @@ -74,7 +74,7 @@ func ParseUserData(userData string) (*clientcmdapi.Config, error) {
// As a kubelet kubeconfig file is provided we basically pull this out as-is
// from cloud-config but merge in our CA data as `certificate-authority-data`
// to save us having to write out a cert file.
func ParseCloudConfig(cloudConfig []byte) (*clientcmdapi.Config, error) {
func ParseCloudConfig(cloudConfig []byte, region string) (*clientcmdapi.Config, error) {

var cloudConfigData []byte
k := &clientcmdapi.Config{}
Expand Down Expand Up @@ -111,6 +111,63 @@ func ParseCloudConfig(cloudConfig []byte) (*clientcmdapi.Config, error) {
return nil, err
}
}
if v.Path == "/etc/eksctl/kubelet.env" {

kubeletEnvContent := v.Content

re := regexp.MustCompile(`CLUSTER_NAME=(.*)`)
fetchedValue := re.FindStringSubmatch(kubeletEnvContent)

if len(fetchedValue) == 0 {
// different format of cloud-config
continue
}

clusterName := fetchedValue[1]

re = regexp.MustCompile(`API_SERVER_URL=(.*)`)
fetchedValue = re.FindStringSubmatch(kubeletEnvContent)
k8sMaster := fetchedValue[1]

re = regexp.MustCompile(`B64_CLUSTER_CA=(.*)`)
fetchedValue = re.FindStringSubmatch(kubeletEnvContent)
base64DecodedCAData := fetchedValue[1]

k = &clientcmdapi.Config{
// Define a cluster stanza
Clusters: map[string]*clientcmdapi.Cluster{
clusterName: {
Server: k8sMaster,
CertificateAuthorityData: []byte(base64DecodedCAData),
},
},
// Define auth based on the kubelet client cert retrieved
AuthInfos: map[string]*clientcmdapi.AuthInfo{
"kubelet": {
Exec: &clientcmdapi.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
Command: "aws",
Args: []string{
"eks",
"get-token",
"--cluster-name",
clusterName,
"--region",
region,
},
},
},
},
// Define a context and set as current
Contexts: map[string]*clientcmdapi.Context{
"kubeletmein": {
Cluster: clusterName,
AuthInfo: "kubelet",
},
},
CurrentContext: "kubeletmein",
}
}
}

if caData != "" {
Expand Down
20 changes: 18 additions & 2 deletions pkg/eks/userdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestParseCloudConfigGzip(t *testing.T) {
t.Errorf("err: %v", err)
}

kubeConfig, err := ParseCloudConfig(cloudConfigData)
kubeConfig, err := ParseCloudConfig(cloudConfigData, region)
if err != nil {
t.Errorf("err: %v", err)
}
Expand All @@ -24,6 +24,22 @@ func TestParseCloudConfigGzip(t *testing.T) {
assert.Contains(t, kubeConfig.Clusters, "test3.eu-west-1.eksctl.io")
}

func TestParseCloudConfigGzip2(t *testing.T) {

cloudConfigData, err := common.FetchMetadataFromFile(filepath.Join("testdata", "cloud-config-two.txt.gz"))
if err != nil {
t.Errorf("err: %v", err)
}

kubeConfig, err := ParseCloudConfig(cloudConfigData, region)
if err != nil {
t.Errorf("err: %v", err)
}

// if you change the testdata, make sure the cluster name matches here
assert.Contains(t, kubeConfig.Clusters, "test3")
}

func TestParseCloudConfigNoGzip(t *testing.T) {

cloudConfigData, err := common.FetchMetadataFromFile(filepath.Join("testdata", "cloud-config.txt.gz"))
Expand All @@ -37,7 +53,7 @@ func TestParseCloudConfigNoGzip(t *testing.T) {
t.Errorf("err: %v", err)
}

kubeConfig, err := ParseCloudConfig(gzipCloudCloudConfigData)
kubeConfig, err := ParseCloudConfig(gzipCloudCloudConfigData, region)
if err != nil {
t.Errorf("err: %v", err)
}
Expand Down

0 comments on commit c026c5f

Please sign in to comment.