-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kac: add new kac package and unit tests
Adds the kac package with just the required functions to interface with the KlusterletAddonConfig resource provided by the klusterlet addon controller as well as unit tests for the new package.
- Loading branch information
Showing
25 changed files
with
2,587 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
package kac | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/golang/glog" | ||
"github.com/openshift-kni/eco-goinfra/pkg/clients" | ||
"github.com/openshift-kni/eco-goinfra/pkg/msg" | ||
kacv1 "github.com/stolostron/klusterlet-addon-controller/pkg/apis/agent/v1" | ||
k8serrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
// Builder provides a struct for the KlusterletAddonConfig resource containing a connection to the cluster and the | ||
// KlusterletAddonConfig definition. | ||
type Builder struct { | ||
// Definition of the KlusterletAddonConfig used to create the object. | ||
Definition *kacv1.KlusterletAddonConfig | ||
// Object of the KlusterletAddonConfig as it is on the cluster. | ||
Object *kacv1.KlusterletAddonConfig | ||
// apiClient used to interact with the cluster. | ||
apiClient *clients.Settings | ||
// errorMsg used to store latest error message from functions that do not return errors. | ||
errorMsg string | ||
} | ||
|
||
// NewBuilder creates a new instance of a KlusterletAddonConfig builder. | ||
func NewBuilder(apiClient *clients.Settings, name, nsname string) *Builder { | ||
glog.V(100).Infof( | ||
"Initializing new KlusterletAddonConfig structure with the following params: name: %s, nsname: %s", name, nsname) | ||
|
||
builder := &Builder{ | ||
apiClient: apiClient, | ||
Definition: &kacv1.KlusterletAddonConfig{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: nsname, | ||
}, | ||
}, | ||
} | ||
|
||
if apiClient == nil { | ||
glog.V(100).Info("The apiClient for the KlusterletAddonConfig is nil") | ||
|
||
builder.errorMsg = "klusterletAddonConfig 'apiClient' cannot be nil" | ||
|
||
return builder | ||
} | ||
|
||
if name == "" { | ||
glog.V(100).Info("The name of the KlusterletAddonConfig is empty") | ||
|
||
builder.errorMsg = "klusterletAddonConfig 'name' cannot be empty" | ||
|
||
return builder | ||
} | ||
|
||
if nsname == "" { | ||
glog.V(100).Info("The namespace of the KlusterletAddonConfig is empty") | ||
|
||
builder.errorMsg = "klusterletAddonConfig 'nsname' cannot be empty" | ||
|
||
return builder | ||
} | ||
|
||
return builder | ||
} | ||
|
||
// Pull pulls an existing KlusterletAddonConfig into a Builder struct. | ||
func Pull(apiClient *clients.Settings, name, nsname string) (*Builder, error) { | ||
glog.V(100).Infof("Pulling existing KlusterletAddonConfig %s under namespace %s from cluster", name, nsname) | ||
|
||
if apiClient == nil { | ||
glog.V(100).Info("The apiClient is empty") | ||
|
||
return nil, fmt.Errorf("klusterletAddonConfig 'apiClient' cannot be nil") | ||
} | ||
|
||
builder := &Builder{ | ||
apiClient: apiClient, | ||
Definition: &kacv1.KlusterletAddonConfig{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: nsname, | ||
}, | ||
}, | ||
} | ||
|
||
if name == "" { | ||
glog.V(100).Info("The name of the KlusterletAddonConfig is empty") | ||
|
||
return nil, fmt.Errorf("klusterletAddonConfig 'name' cannot be empty") | ||
} | ||
|
||
if nsname == "" { | ||
glog.V(100).Info("The namespace of the KlusterletAddonConfig is empty") | ||
|
||
return nil, fmt.Errorf("klusterletAddonConfig 'nsname' cannot be empty") | ||
} | ||
|
||
if !builder.Exists() { | ||
glog.V(100).Info("The KlusterletAddonConfig %s does not exist in namespace %s", name, nsname) | ||
|
||
return nil, fmt.Errorf("klusterletAddonConfig object %s does not exist in namespace %s", name, nsname) | ||
} | ||
|
||
builder.Definition = builder.Object | ||
|
||
return builder, nil | ||
} | ||
|
||
// Exists checks whether the given KlusterletAddonConfig exists on the cluster. | ||
func (builder *Builder) Exists() bool { | ||
if valid, _ := builder.validate(); !valid { | ||
return false | ||
} | ||
|
||
glog.V(100).Infof( | ||
"Checking if KlusterletAddonConfig %s exists in namespace %s", builder.Definition.Name, builder.Definition.Namespace) | ||
|
||
klusterletAddonConfig := &kacv1.KlusterletAddonConfig{} | ||
err := builder.apiClient.Get(context.TODO(), runtimeclient.ObjectKey{ | ||
Name: builder.Definition.Name, | ||
Namespace: builder.Definition.Namespace, | ||
}, klusterletAddonConfig) | ||
|
||
if err == nil { | ||
builder.Object = klusterletAddonConfig | ||
} | ||
|
||
return err == nil || !k8serrors.IsNotFound(err) | ||
} | ||
|
||
// Create makes a KlusterletAddonConfig on the cluster if it does not already exist. | ||
func (builder *Builder) Create() (*Builder, error) { | ||
if valid, err := builder.validate(); !valid { | ||
return nil, err | ||
} | ||
|
||
glog.V(100).Infof( | ||
"Creating KlusterletAddonConfig %s in namespace %s", builder.Definition.Name, builder.Definition.Namespace) | ||
|
||
if builder.Exists() { | ||
return builder, nil | ||
} | ||
|
||
err := builder.apiClient.Create(context.TODO(), builder.Definition) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
builder.Object = builder.Definition | ||
|
||
return builder, err | ||
} | ||
|
||
// Update changes the existing KlusterletAddonConfig resource on the cluster, falling back to deleting and recreating if | ||
// the update fails when force is set. | ||
func (builder *Builder) Update(force bool) (*Builder, error) { | ||
if valid, err := builder.validate(); !valid { | ||
return nil, err | ||
} | ||
|
||
glog.V(100).Infof( | ||
"Updating KlusterletAddonConfig %s in namespace %s", builder.Definition.Name, builder.Definition.Namespace) | ||
|
||
if !builder.Exists() { | ||
glog.V(100).Infof( | ||
"KlusterletAddonConfig %s does not exist in namespace %s", builder.Definition.Name, builder.Definition.Namespace) | ||
|
||
return nil, fmt.Errorf("cannot update non-existent klusterletAddonConfig") | ||
} | ||
|
||
err := builder.apiClient.Update(context.TODO(), builder.Definition) | ||
if err != nil { | ||
if force { | ||
glog.V(100).Infof(msg.FailToUpdateNotification("klusterletAddonConfig", builder.Definition.Name)) | ||
|
||
err := builder.Delete() | ||
if err != nil { | ||
glog.V(100).Infof(msg.FailToUpdateError("klusterletAddonConfig", builder.Definition.Name)) | ||
|
||
return nil, err | ||
} | ||
|
||
return builder.Create() | ||
} | ||
|
||
return nil, err | ||
} | ||
|
||
builder.Object = builder.Definition | ||
|
||
return builder, nil | ||
} | ||
|
||
// Delete removes a KlusterletAddonConfig from the cluster if it exists. | ||
func (builder *Builder) Delete() error { | ||
if valid, err := builder.validate(); !valid { | ||
return err | ||
} | ||
|
||
glog.V(100).Infof( | ||
"Deleting KlusterletAddonConfig %s in namespace %s", builder.Definition.Name, builder.Definition.Namespace) | ||
|
||
if !builder.Exists() { | ||
glog.V(100).Infof( | ||
"KlusterletAddonConfig %s in namespace %s already does not exist", | ||
builder.Definition.Name, builder.Definition.Namespace) | ||
|
||
builder.Object = nil | ||
|
||
return nil | ||
} | ||
|
||
err := builder.apiClient.Delete(context.TODO(), builder.Object) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
builder.Object = nil | ||
|
||
return nil | ||
} | ||
|
||
// validate checks that the builder, definition, and apiClient are properly initialized and there is no errorMsg. | ||
func (builder *Builder) validate() (bool, error) { | ||
resourceCRD := "klusterletAddonConfig" | ||
|
||
if builder == nil { | ||
glog.V(100).Infof("The %s builder is uninitialized", resourceCRD) | ||
|
||
return false, fmt.Errorf("error: received nil %s builder", resourceCRD) | ||
} | ||
|
||
if builder.Definition == nil { | ||
glog.V(100).Infof("The %s is uninitialized", resourceCRD) | ||
|
||
return false, fmt.Errorf(msg.UndefinedCrdObjectErrString(resourceCRD)) | ||
} | ||
|
||
if builder.apiClient == nil { | ||
glog.V(100).Infof("The %s builder apiClient is nil", resourceCRD) | ||
|
||
return false, fmt.Errorf("%s builder cannot have nil apiClient", resourceCRD) | ||
} | ||
|
||
if builder.errorMsg != "" { | ||
glog.V(100).Infof("The %s builder has error message %s", resourceCRD, builder.errorMsg) | ||
|
||
return false, fmt.Errorf(builder.errorMsg) | ||
} | ||
|
||
return true, nil | ||
} |
Oops, something went wrong.