Skip to content

Commit

Permalink
connectivitycheckcontroller: add to library-go
Browse files Browse the repository at this point in the history
  • Loading branch information
sanchezl committed Aug 5, 2020
1 parent e68ef47 commit 22e2f2b
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package connectivitycheckcontroller

import (
"context"

operatorv1 "github.com/openshift/api/operator/v1"
"github.com/openshift/api/operatorcontrolplane/v1alpha1"
operatorcontrolplaneclient "github.com/openshift/client-go/operatorcontrolplane/clientset/versioned"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/openshift/library-go/pkg/controller/factory"
"github.com/openshift/library-go/pkg/operator/events"
"github.com/openshift/library-go/pkg/operator/resource/resourcehelper"
"github.com/openshift/library-go/pkg/operator/v1helpers"
)

type ConnectivityCheckController interface {
factory.Controller

WithPodNetworkConnectivityCheckFn(podNetworkConnectivityCheckFn PodNetworkConnectivityCheckFunc) ConnectivityCheckController
}

func NewConnectivityCheckController(
namespace string,
operatorClient v1helpers.OperatorClient,
operatorcontrolplaneClient *operatorcontrolplaneclient.Clientset,
triggers []factory.Informer,
recorder events.Recorder,
) ConnectivityCheckController {
c := &connectivityCheckController{
namespace: namespace,
operatorClient: operatorClient,
operatorcontrolplaneClient: operatorcontrolplaneClient,
}

allTriggers := []factory.Informer{operatorClient.Informer()}
allTriggers = append(allTriggers, triggers...)

c.Controller = factory.New().
WithSync(c.Sync).
WithInformers(allTriggers...).
ToController("ConnectivityCheckController", recorder.WithComponentSuffix("connectivity-check-controller"))
return c
}

type connectivityCheckController struct {
factory.Controller
namespace string
operatorClient v1helpers.OperatorClient
operatorcontrolplaneClient *operatorcontrolplaneclient.Clientset

podNetworkConnectivityCheckFn PodNetworkConnectivityCheckFunc
}

type PodNetworkConnectivityCheckFunc func(ctx context.Context, syncContext factory.SyncContext) ([]*v1alpha1.PodNetworkConnectivityCheck, error)

func (c *connectivityCheckController) WithPodNetworkConnectivityCheckFn(podNetworkConnectivityCheckFn PodNetworkConnectivityCheckFunc) ConnectivityCheckController {
c.podNetworkConnectivityCheckFn = podNetworkConnectivityCheckFn
return c
}

func (c *connectivityCheckController) Sync(ctx context.Context, syncContext factory.SyncContext) error {
operatorSpec, _, _, err := c.operatorClient.GetOperatorState()
if err != nil {
return err
}
switch operatorSpec.ManagementState {
case operatorv1.Managed:
case operatorv1.Unmanaged:
return nil
case operatorv1.Removed:
return nil
default:
syncContext.Recorder().Warningf("ManagementStateUnknown", "Unrecognized operator management state %q", operatorSpec.ManagementState)
return nil
}

checks, err := c.podNetworkConnectivityCheckFn(ctx, syncContext)
if err != nil {
return err
}

pnccClient := c.operatorcontrolplaneClient.ControlplaneV1alpha1().PodNetworkConnectivityChecks(c.namespace)
for _, check := range checks {
existing, err := pnccClient.Get(ctx, check.Name, metav1.GetOptions{})
if err == nil {
if equality.Semantic.DeepEqual(existing.Spec, check.Spec) {
// already exists, no changes, skip
continue
}
updated := existing.DeepCopy()
updated.Spec = *check.Spec.DeepCopy()
_, err := pnccClient.Update(ctx, updated, metav1.UpdateOptions{})
if err != nil {
syncContext.Recorder().Warningf("EndpointDetectionFailure", "%s: %v", resourcehelper.FormatResourceForCLIWithNamespace(check), err)
continue
}
syncContext.Recorder().Eventf("EndpointCheckUpdated", "Updated %s because it changed.", resourcehelper.FormatResourceForCLIWithNamespace(check))
}
if apierrors.IsNotFound(err) {
_, err = pnccClient.Create(ctx, check, metav1.CreateOptions{})
}
if err != nil {
syncContext.Recorder().Warningf("EndpointDetectionFailure", "%s: %v", resourcehelper.FormatResourceForCLIWithNamespace(check), err)
continue
}
syncContext.Recorder().Eventf("EndpointCheckCreated", "Created %s because it was missing.", resourcehelper.FormatResourceForCLIWithNamespace(check))
}

// TODO for checks which longer exist, mark them as completed

// TODO reap old connectivity checks

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package connectivitycheckcontroller

import (
"strings"

v1 "github.com/openshift/api/config/v1"
"github.com/openshift/api/operatorcontrolplane/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// new PodNetworkConnectivityCheck whose name is '$(SOURCE)-to-$(TARGET)'.
// Use the WithSource and WithTarget option funcs to replace the '$(SOURCE)' and '$(TARGET)' tokens.
func NewPodNetworkConnectivityCheckTemplate(address, namespace string, options ...func(*v1alpha1.PodNetworkConnectivityCheck)) *v1alpha1.PodNetworkConnectivityCheck {
check := &v1alpha1.PodNetworkConnectivityCheck{
ObjectMeta: metav1.ObjectMeta{
Name: "$(SOURCE)-to-$(TARGET)",
Namespace: namespace,
},
Spec: v1alpha1.PodNetworkConnectivityCheckSpec{
TargetEndpoint: address,
},
}
for _, option := range options {
option(check)
}
return check
}

// WithTlsClientCert option specifies the name of the secret in the check namespace that
// contains a tls client certificate (and key) to use when performing the check.
func WithTlsClientCert(secretName string) func(*v1alpha1.PodNetworkConnectivityCheck) {
return func(check *v1alpha1.PodNetworkConnectivityCheck) {
if len(secretName) > 0 {
check.Spec.TLSClientCert = v1.SecretNameReference{Name: secretName}
}
}
}

// WithSource option replaces the $(SOURCE) token in the name.
func WithSource(source string) func(*v1alpha1.PodNetworkConnectivityCheck) {
return func(check *v1alpha1.PodNetworkConnectivityCheck) {
check.Name = strings.Replace(check.Name, "$(SOURCE)", source, -1)
}
}

// WithTarget option replaces the $(TARGET) token in the name.
func WithTarget(target string) func(*v1alpha1.PodNetworkConnectivityCheck) {
return func(check *v1alpha1.PodNetworkConnectivityCheck) {
check.Name = strings.Replace(check.Name, "$(TARGET)", target, -1)
}
}

0 comments on commit 22e2f2b

Please sign in to comment.