diff --git a/cluster/command.go b/cluster/command.go index 8d492ce..21ddad0 100644 --- a/cluster/command.go +++ b/cluster/command.go @@ -2,10 +2,11 @@ package cluster import ( "context" - + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/clientcmd" ) @@ -22,28 +23,43 @@ func NewCommand(kubeconfig string) (*KubernetesCommand, error) { return nil, err } - return &KubernetesCommand{clientset.AppsV1()}, nil + return &KubernetesCommand{clientset.AppsV1(), clientset.CoreV1()}, nil } // Command provides an interface for creating envcheck entities in a cluster. type Command interface { CreateDaemon(DaemonConfig) error CreatePinger(PingerConfig) error + CreateService(DaemonConfig) error } // KubernetesCommand is a k8s implementation of the Command interface. type KubernetesCommand struct { appsv1.AppsV1Interface + corev1.CoreV1Interface } -// CreateDaemon applies a envchecker daemonset config to the current K8S environment. +// CreateDaemon creates an envchecker daemonset in the current K8S environment. func (kc *KubernetesCommand) CreateDaemon(config DaemonConfig) error { _, err := kc.DaemonSets(config.Namespace).Create(context.TODO(), Daemon(config), metav1.CreateOptions{}) + if err != nil && errors.IsAlreadyExists(err) { + _, err = kc.DaemonSets(config.Namespace).Update(context.TODO(), Daemon(config), metav1.UpdateOptions{}) + } + return err +} + +// CreateService creates an envchecker service in the current K8S environment. +func (kc *KubernetesCommand) CreateService(config DaemonConfig) error { + svc := Service(config) + _, err := kc.Services(config.Namespace).Create(context.TODO(), svc, metav1.CreateOptions{}) return err } -// CreatePinger applies a pinger daemonset config to the current K8S environment. +// CreatePinger creates a pinger daemonset in the current K8S environment. func (kc *KubernetesCommand) CreatePinger(config PingerConfig) error { _, err := kc.DaemonSets(config.Namespace).Create(context.TODO(), Pinger(config), metav1.CreateOptions{}) + if err != nil && errors.IsAlreadyExists(err) { + _, err = kc.DaemonSets(config.Namespace).Update(context.TODO(), Pinger(config), metav1.UpdateOptions{}) + } return err } diff --git a/cluster/resources.go b/cluster/resources.go index ed76740..8457647 100644 --- a/cluster/resources.go +++ b/cluster/resources.go @@ -2,6 +2,7 @@ package cluster import ( "fmt" + "k8s.io/apimachinery/pkg/util/intstr" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" @@ -41,6 +42,36 @@ const ( LabelVersion = "app.kubernetes.io/version" ) +var Local = v1.ServiceInternalTrafficPolicyLocal + +func Service(config DaemonConfig) *v1.Service { + return &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: DaemonSetName, + Namespace: config.Namespace, + Labels: map[string]string{ + LabelManagedBy: ManagedBy, + LabelName: DaemonSetName, + LabelVersion: config.Version, + }, + }, + Spec: v1.ServiceSpec{ + Selector: map[string]string{ + LabelName: DaemonSetName, + }, + InternalTrafficPolicy: &Local, + Ports: []v1.ServicePort{ + { + Name: "http", + Protocol: v1.ProtocolTCP, + TargetPort: intstr.FromString("http"), + Port: config.Port, + }, + }, + }, + } +} + // Daemon creates the envchecker daemon set resource from the provided DaemonConfig. func Daemon(config DaemonConfig) *appsv1.DaemonSet { return &appsv1.DaemonSet{ @@ -51,8 +82,7 @@ func Daemon(config DaemonConfig) *appsv1.DaemonSet { Spec: appsv1.DaemonSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ - LabelName: DaemonSetName, - LabelVersion: config.Version, + LabelName: DaemonSetName, }, }, Template: v1.PodTemplateSpec{ diff --git a/cmd/envcheckctl/exec_daemon.go b/cmd/envcheckctl/exec_daemon.go index 05854ad..e1c6ff1 100644 --- a/cmd/envcheckctl/exec_daemon.go +++ b/cmd/envcheckctl/exec_daemon.go @@ -20,7 +20,13 @@ func ExecDaemon(config EnvcheckConfig) { Version: Revision, } err = command.CreateDaemon(dc) + if err != nil { log.Fatalf("createDaemon=failed err='%v'\n", err) } + + err = command.CreateService(dc) + if err != nil { + log.Fatalf("createService=failed err='%v'\n", err) + } }