Skip to content

Commit

Permalink
Merge pull request #19 from newrelic/cciutea/add_auto_config
Browse files Browse the repository at this point in the history
Added auto detection for kubelet client config
  • Loading branch information
cristianciutea authored Nov 16, 2020
2 parents d20b72c + b226a2f commit 8100246
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 26 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ GOPATH := $(shell go env GOPATH)
GORELEASER_VERSION := v0.129.0
GORELEASER_SHA256 := e9e61de6565ad4acbe33a944abbeaf0d75582c10b89b793c99acd41a0846c166
GORELEASER_BIN ?= bin/goreleaser
GOLANGCILINT_VERSION = v1.24.0
GOLANGCILINT_VERSION = v1.27.0
GOLANGCI_LINT_BIN = bin/golangci-lint

all: build
Expand Down
4 changes: 3 additions & 1 deletion cmd/discovery/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
"time"

cfg "github.com/newrelic/nri-discovery-kubernetes/internal/config"
"github.com/newrelic/nri-discovery-kubernetes/internal/discovery"
Expand All @@ -20,7 +21,8 @@ func main() {

config := cfg.NewConfig(Version)

kubelet, err := kubernetes.NewKubelet(config.Port, config.TLS)
timeout := time.Duration(config.Timeout) * time.Millisecond
kubelet, err := kubernetes.NewKubelet(config.Host, config.Port, config.TLS, config.IsAutoConfig(), timeout)
if err != nil {
log.Printf("failed to get Kubernetes configuration: %s", err)
os.Exit(1)
Expand Down
27 changes: 24 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,40 @@ module github.com/newrelic/nri-discovery-kubernetes
go 1.13

require (
cloud.google.com/go v0.38.0 // indirect
github.com/Azure/go-autorest/autorest v0.9.0 // indirect
github.com/evanphx/json-patch v4.2.0+incompatible // indirect
github.com/gogo/protobuf v1.3.1 // indirect
github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.3.0 // indirect
github.com/google/uuid v1.1.1 // indirect
github.com/gophercloud/gophercloud v0.1.0 // indirect
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 // indirect
github.com/hashicorp/golang-lru v0.5.1 // indirect
github.com/imdario/mergo v0.3.8 // indirect
github.com/json-iterator/go v1.1.8 // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/newrelic/nri-kubernetes v1.26.5
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/sirupsen/logrus v1.2.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.6.2
github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 // indirect
golang.org/x/net v0.0.0-20191112182307-2180aed22343 // indirect
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
google.golang.org/appengine v1.6.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.2.5 // indirect
k8s.io/api v0.0.0-20191115095533-47f6de673b26
k8s.io/apimachinery v0.0.0-20191115015347-3c7067801da2
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33
k8s.io/api v0.0.0-20180521142803-feb48db456a5
k8s.io/apimachinery v0.0.0-20180515182440-31dade610c05
k8s.io/client-go v7.0.0+incompatible
k8s.io/klog v1.0.0 // indirect
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a // indirect
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6 // indirect
)
49 changes: 49 additions & 0 deletions go.sum

Large diffs are not rendered by default.

31 changes: 30 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,31 @@ import (
const (
namespaces = "namespaces"
port = "port"
Host = "host"
insecure = "insecure"
timeout = "timeout"
tls = "tls"
envPrefix = "NRIA"

DefaultHost = "localhost"
DefaultPort = 10255
)

var _ = flag.String(namespaces, "", "(optional, default '') Comma separated list of namespaces to discover pods on")
var _ = flag.Bool(insecure, false, `(optional, default false, deprecated) Use insecure (non-ssl) connection.
For backwards compatibility this flag takes precedence over 'tls')`)
var _ = flag.Int(timeout, 5000, "(optional, default 5000) timeout in ms")
var _ = flag.Bool(tls, false, "(optional, default false) Use secure (tls) connection")
var _ = flag.Int(port, 10255, "(optional, default 10255) Port used to connect to the kubelet")
var _ = flag.Int(port, DefaultPort, "(optional, default 10255) Port used to connect to the kubelet")
var _ = flag.String(Host, DefaultHost, "(optional, default "+DefaultHost+") Host used to connect to the kubelet")

// Config defined the currently accepted configuration parameters of the Discoverer
type Config struct {
Namespaces []string
Port int
Host string
TLS bool
Timeout int
}

func splitStrings(str string) []string {
Expand All @@ -35,14 +44,32 @@ func splitStrings(str string) []string {
return []string{}
}

// IsFlagPassed checks if a particular command line argument was provided or not.
func IsFlagPassed(name string) bool {
found := false
flag.Visit(func(f *flag.Flag) {
if f.Name == name {
found = true
}
})
return found
}

// IsAutoConfig returns true if no config parameter was provided as cmd line arg.
func (c *Config) IsAutoConfig() bool {
return !IsFlagPassed(Host) && !IsFlagPassed(port) && !IsFlagPassed(tls)
}

func NewConfig(version string) Config {
flag.Parse()

v := viper.New()
_ = v.BindPFlag(namespaces, flag.Lookup(namespaces))
_ = v.BindPFlag(port, flag.Lookup(port))
_ = v.BindPFlag(Host, flag.Lookup(Host))
_ = v.BindPFlag(tls, flag.Lookup(tls))
_ = v.BindPFlag(insecure, flag.Lookup(insecure))
_ = v.BindPFlag(timeout, flag.Lookup(timeout))

v.SetEnvPrefix(envPrefix)
v.AutomaticEnv()
Expand All @@ -56,6 +83,8 @@ func NewConfig(version string) Config {
return Config{
Namespaces: splitStrings(v.GetString(namespaces)),
Port: v.GetInt(port),
Host: v.GetString(Host),
TLS: useTLS,
Timeout: v.GetInt(timeout),
}
}
48 changes: 46 additions & 2 deletions internal/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ package http
import (
"crypto/tls"
"errors"
nriK8sClient "github.com/newrelic/nri-kubernetes/src/client"
nriKubeletClient "github.com/newrelic/nri-kubernetes/src/kubelet/client"
"github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
netHttp "net/http"
"net/url"
"os"
"time"
)

type HttpClient interface {
Expand All @@ -26,12 +32,13 @@ func (c *httpClient) Get(path string) ([]byte, error) {
return nil, err
}

defer resp.Body.Close()
buff, _ := ioutil.ReadAll(resp.Body)

if resp.StatusCode != http.StatusOK {
return nil, errors.New(resp.Status)
}

buff, _ := ioutil.ReadAll(resp.Body)
_ = resp.Body.Close()
return buff, nil
}

Expand All @@ -47,3 +54,40 @@ func NewClient(url url.URL, token string) HttpClient {
token: token,
}
}

// kubeletClient addapts the nri-kubernetes kubelet client.
type kubeletClient struct {
client nriK8sClient.HTTPClient
}

// NewKubeletClient creates a new kubeletClient instance.
func NewKubeletClient(nodeName string, timeout time.Duration) (HttpClient, error) {
logger := logrus.New()
logger.SetOutput(os.Stderr)
d, err := nriKubeletClient.NewDiscoverer(nodeName, logger)
if err != nil {
return nil, err
}
client, err := d.Discover(timeout)
if err != nil {
return nil, err
}
return &kubeletClient{
client: client,
}, nil
}

func (kc *kubeletClient) Get(path string) ([]byte, error) {
resp, err := kc.client.Do(netHttp.MethodGet, path)
if err != nil {
return nil, err
}

defer resp.Body.Close()
buff, _ := ioutil.ReadAll(resp.Body)

if resp.StatusCode != netHttp.StatusOK {
return nil, errors.New(resp.Status)
}
return buff, nil
}
41 changes: 28 additions & 13 deletions internal/kubernetes/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ package kubernetes
import (
"encoding/json"
"fmt"
"net/url"
"os"
"path/filepath"
"strconv"

configPkg "github.com/newrelic/nri-discovery-kubernetes/internal/config"
"github.com/newrelic/nri-discovery-kubernetes/internal/http"
"github.com/newrelic/nri-discovery-kubernetes/internal/utils"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"net/url"
"os"
"path/filepath"
"strconv"
"time"
)

const host = "localhost"
const podsPath = "/pods"
const clusterNameEnvVar = "CLUSTER_NAME"
const kubeletHostEnvVar = "NRK8S_NODE_NAME"
const nodeNameEnvVar = "NRK8S_NODE_NAME"

type PortsMap map[string]int32
type LabelsMap map[string]string
Expand Down Expand Up @@ -147,7 +148,7 @@ func getClusterName() string {
return clusterName
}

func NewKubelet(port int, useTLS bool) (Kubelet, error) {
func NewKubelet(host string, port int, useTLS bool, autoConfig bool, timeout time.Duration) (Kubelet, error) {
config, err := rest.InClusterConfig()
// not inside the cluster?
if err != nil {
Expand All @@ -159,12 +160,26 @@ func NewKubelet(port int, useTLS bool) (Kubelet, error) {
}

clusterName := getClusterName()
kubeletHost, isKubeletHostSet := os.LookupEnv(kubeletHostEnvVar)
nodeName, isNodeNameSet := os.LookupEnv(nodeNameEnvVar)
if autoConfig && isNodeNameSet {
client, err := http.NewKubeletClient(nodeName, timeout)
if err != nil {
logrus.WithError(err).Warn("failed to initialize kubelet client")
} else {
kubelet := &kubelet{
client: &client,
NodeName: nodeName,
ClusterName: clusterName,
}
return kubelet, nil
}
}

if !isKubeletHostSet {
// If the environment variable represented by kubeletHostEnvVar is not set,
// fallback to the default value.
kubeletHost = host
// host provided by cmd line arg has higher precedence.
// if host cmd line arg is not provided use NRK8S_NODE_NAME in case is set, otherwise localhost.
var kubeletHost = host
if isNodeNameSet && !configPkg.IsFlagPassed(configPkg.Host) {
kubeletHost = nodeName
}

hostUrl := makeUrl(kubeletHost, port, useTLS)
Expand Down
5 changes: 0 additions & 5 deletions internal/kubernetes/kubelet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ import (
"testing"
)

func pointerToBool(b bool) *bool {
return &b
}

func getPod(phase v1.PodPhase, containerStatus ...v1.ContainerStatus) v1.Pod {
return v1.Pod{
Status: v1.PodStatus{
Expand All @@ -29,7 +25,6 @@ func buildContainerStatus(containerName string, containerState v1.ContainerState
Image: "k8s.gcr.io/kube-scheduler:v1.18.2",
ImageID: "docker-pullable://k8s.gcr.io/kube-scheduler@sha256:69f90a33b64c99e4c78e3cae36b0c767729b5a54203aa35524b1033708d1b482",
ContainerID: "docker://fd5fd1918be39db9992067f87f4daa755c83adbec63aece69879fb29d45514a0",
Started: pointerToBool(true),
}
}

Expand Down

0 comments on commit 8100246

Please sign in to comment.