Skip to content

Commit

Permalink
Auto detect cluster name on eks, aks, gke (#131)
Browse files Browse the repository at this point in the history
* auto detect cluster name on eks, aks, gke

* Fix hash printing
  • Loading branch information
jmorganca committed Jul 28, 2021
1 parent 7dc57dd commit 1991fdf
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 6 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.16
require (
github.com/AlecAivazis/survey/v2 v2.2.13
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/aws/aws-sdk-go v1.38.35
github.com/cli/browser v1.1.0
github.com/docker/go-units v0.4.0
github.com/envoyproxy/protoc-gen-validate v0.6.2-0.20210710165204-c2b08efda458
Expand Down
4 changes: 3 additions & 1 deletion helm/charts/infra/charts/engine/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ spec:
ports:
- containerPort: 80
env:
{{- if .Values.name }}
- name: INFRA_ENGINE_NAME
value: {{ required "Value name is required" .Values.name | quote }}
value: {{ .Values.name | quote }}
{{- end }}
- name: INFRA_ENGINE_REGISTRY
value: {{ required "Value registry is required" .Values.registry | quote }}
- name: INFRA_ENGINE_API_KEY
Expand Down
1 change: 0 additions & 1 deletion helm/charts/infra/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ ingress:
labels: {}

engine:
name: default
registry: "infra"
image:
repository: infrahq/infra
Expand Down
3 changes: 0 additions & 3 deletions internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,9 +981,6 @@ func newEngineCmd() *cobra.Command {
if options.Registry == "" {
return errors.New("registry not specified (--registry or INFRA_ENGINE_REGISTRY)")
}
if options.Name == "" {
return errors.New("name not specified (--name or INFRA_ENGINE_NAME)")
}
if options.Registry != "infra" && options.APIKey == "" {
return errors.New("api-key not specified (--api-key or INFRA_ENGINE_API_KEY)")
}
Expand Down
13 changes: 12 additions & 1 deletion internal/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,25 @@ func Run(options Options) error {
return
}

var name string
if options.Name == "" {
name, err = kubernetes.Name()
if err != nil {
fmt.Println(err)
return
}
} else {
name = options.Name
}

saToken, err := kubernetes.SaToken()
if err != nil {
fmt.Println(err)
return
}

res, err := client.CreateDestination(context.Background(), &v1.CreateDestinationRequest{
Name: options.Name,
Name: name,
Type: v1.DestinationType_KUBERNETES,
Kubernetes: &v1.CreateDestinationRequest_Kubernetes{
Ca: string(ca),
Expand Down
167 changes: 167 additions & 0 deletions internal/engine/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ package engine
import (
"bytes"
"context"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"sync"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/google/shlex"
"github.com/jessevdk/go-flags"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -131,6 +138,166 @@ func (k *Kubernetes) UpdatePermissions(rbs []RoleBinding) error {
return nil
}

// Originally from https://github.com/DataDog/datadog-agent
// Apache 2.0 license
func eksClusterName() (string, error) {
res, err := http.Get("http://169.254.169.254/latest/dynamic/instance-identity/document")
if err != nil {
return "", err
}

if res.StatusCode != http.StatusOK {
return "", errors.New("received non-OK code from metadata service")
}

body, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", err
}

var identity struct {
Region string
InstanceID string
}

err = json.Unmarshal(body, &identity)
if err != nil {
return "", err
}

awsSess, err := session.NewSession(&aws.Config{
Region: aws.String(identity.Region),
})
if err != nil {
return "", err
}

connection := ec2.New(awsSess)
ec2Tags, err := connection.DescribeTagsWithContext(context.Background(),
&ec2.DescribeTagsInput{
Filters: []*ec2.Filter{{
Name: aws.String("resource-id"),
Values: []*string{
aws.String(identity.InstanceID),
},
}},
},
)

if err != nil {
return "", err
}

tags := []string{}
for _, tag := range ec2Tags.Tags {
tags = append(tags, fmt.Sprintf("%s:%s", *tag.Key, *tag.Value))
}

var clusterName string
for _, tag := range tags {
if strings.HasPrefix(tag, "kubernetes.io/cluster/") { // tag key format: kubernetes.io/cluster/clustername"
key := strings.Split(tag, ":")[0]
clusterName = strings.Split(key, "/")[2] // rely on ec2 tag format to extract clustername
break
}
}

if clusterName == "" {
return "", errors.New("unable to parse cluster name from EC2 tags")
}

return clusterName, nil
}

// Originally from https://github.com/DataDog/datadog-agent
// Apache 2.0 license
func gkeClusterName() (string, error) {
req, err := http.NewRequest("GET", "http://169.254.169.254/computeMetadata/v1/instance/attributes/cluster-name", nil)
if err != nil {
return "", err
}

req.Header.Add("Metadata-Flavor", "Google")
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
return "", errors.New("received non-OK code from metadata service")
}

name, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", err
}

return string(name), nil
}

// Originally from https://github.com/DataDog/datadog-agent
// Apache 2.0 license
func aksClusterName() (string, error) {
req, err := http.NewRequest("GET", "http://169.254.169.254/metadata/instance/compute/resourceGroupName?api-version=2017-08-01&format=text", nil)
if err != nil {
return "", err
}

req.Header.Add("Metadata", "true")
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
return "", errors.New("received non-OK code from metadata service")
}

all, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", fmt.Errorf("error while reading response from azure metadata endpoint: %s", err)
}

splitAll := strings.Split(string(all), "_")
if len(splitAll) < 4 || strings.ToLower(splitAll[0]) != "mc" {
return "", fmt.Errorf("cannot parse the clustername from resource group name: %s", all)
}

return splitAll[len(splitAll)-2], nil
}

func (k *Kubernetes) Name() (string, error) {
name, err := eksClusterName()
if err == nil {
return name, nil
}

name, err = gkeClusterName()
if err == nil {
return name, nil
}

name, err = aksClusterName()
if err == nil {
return name, nil
}

fmt.Println("could not fetch cluster name, resorting to hashed cluster CA")

ca, err := k.CA()
if err != nil {
return "", err
}

h := sha1.New()
h.Write(ca)
hash := h.Sum(nil)

return "cluster-" + hex.EncodeToString(hash)[:8], nil
}

func (k *Kubernetes) Namespace() (string, error) {
contents, err := ioutil.ReadFile(NamespaceFilePath)
if err != nil {
Expand Down

0 comments on commit 1991fdf

Please sign in to comment.