Skip to content

Commit

Permalink
chore: add kubeclient mock (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
azrod authored Oct 8, 2024
1 parent 41b039b commit c640b95
Show file tree
Hide file tree
Showing 22 changed files with 208 additions and 75 deletions.
3 changes: 2 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ linters:
- goheader # Checks is file header matches to pattern [fast: true, auto-fix: false]
- gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
- goimports # In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true]
- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
# ! Ignore temporary due to issue with diun package
# - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
- goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
- gosec #(gas): Inspects source code for security problems [fast: false, auto-fix: false]
Expand Down
1 change: 0 additions & 1 deletion api/v1alpha1/alert_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ type (

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=alertconfig,scope=Namespaced

type AlertConfig struct {
metav1.TypeMeta `json:",inline"`
Expand Down
2 changes: 1 addition & 1 deletion cmd/kimup/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func refreshIfRequired(an annotations.Annotation, image v1alpha1.Image) {
}
}

func setTagIfNotExists(ctx context.Context, kubeClient *kubeclient.Client, an annotations.Annotation, image *v1alpha1.Image) error {
func setTagIfNotExists(ctx context.Context, kubeClient kubeclient.Interface, an annotations.Annotation, image *v1alpha1.Image) error {
if an.Tag().IsNull() {
a, err := actions.GetAction(actions.Apply)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cmd/kimup/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

type locks map[string]*sync.RWMutex

func initScheduler(ctx context.Context, k *kubeclient.Client) {
func initScheduler(ctx context.Context, k kubeclient.Interface) {
l := make(locks)

// Start Crontab client
Expand Down Expand Up @@ -122,7 +122,7 @@ func initScheduler(ctx context.Context, k *kubeclient.Client) {
AvailableTags: tagsAvailable,
}, &image, action.Data)
if err := a.Execute(ctx); err != nil {
log.Errorf("Error executing action: %v", err)
log.Errorf("Error executing action(%s): %v", action.Type, err)
continue
}
}
Expand Down
22 changes: 17 additions & 5 deletions cmd/webhook/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
v1 "k8s.io/client-go/applyconfigurations/admissionregistration/v1"

"github.com/orange-cloudavenue/kube-image-updater/internal/kubeclient"
)

// generateTLS generates a self-signed certificate for the webhook server
Expand Down Expand Up @@ -185,14 +188,14 @@ func writeNewCA(caPEM *bytes.Buffer, filePath string) {
}

func applyManifest(file string) {
// Lire le manifest YAML
// read the manifest file
manifestBytes, err := os.ReadFile(file)
if err != nil {
warningLogger.Printf("Failed to read manifest: %v\n", err)
return
}

// Décoder le manifest YAML en objets Kubernetes
// decode the manifest to unstructured object
decoder := serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer()
obj := &unstructured.Unstructured{}
_, _, err = decoder.Decode(manifestBytes, nil, obj)
Expand All @@ -201,10 +204,19 @@ func applyManifest(file string) {
return
}

// Appliquer les objets Kubernetes au cluster
gvr := obj.GroupVersionKind().GroupVersion().WithResource("mutatingwebhookconfigurations")
_, err = kubeClient.GetDynamicClient().Resource(gvr).Apply(context.TODO(), obj.GetName(), obj, metav1.ApplyOptions{Force: true, FieldManager: "kumi-webhook"})
// convert the unstructured object to typed object
mutatingWebhookConfiguration, err := kubeclient.DecodeUnstructured[v1.MutatingWebhookConfigurationApplyConfiguration](obj)
if err != nil {
warningLogger.Printf("Failed to decode manifest: %v\n", err)
return
}

// apply the manifest
if _, err := kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Apply(
context.TODO(),
&mutatingWebhookConfiguration,
metav1.ApplyOptions{Force: true, FieldManager: "kumi-webhook"},
); err != nil {
warningLogger.Printf("Failed to apply manifest: %v\n", err)
return
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var (
codecs = serializer.NewCodecFactory(runtimeScheme)
deserializer = codecs.UniversalDeserializer()

kubeClient *client.Client
kubeClient client.Interface
manifestWebhookPath string = "./config/manifests/mutatingWebhookConfiguration.yaml"

// Prometheus metrics
Expand Down
4 changes: 2 additions & 2 deletions cmd/webhook/webhook-configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import (
// createOrUpdateMutatingWebhookConfiguration creates or updates the mutating webhook configuration
// for the webhook service. The CA is generated and used for the webhook.
// This function create the request to the Kubernetes API server to create or update the mutating webhook configuration.
func createOrUpdateMutatingWebhookConfiguration(caPEM *bytes.Buffer, webhookService, webhookNamespace string, k *client.Client) error {
func createOrUpdateMutatingWebhookConfiguration(caPEM *bytes.Buffer, webhookService, webhookNamespace string, k client.Interface) error {
infoLogger.Println("Initializing the kube client...")

mutatingWebhookConfigV1Client := k.GetKubeClient().AdmissionregistrationV1()
mutatingWebhookConfigV1Client := k.AdmissionregistrationV1()

var clientConfig admissionregistrationv1.WebhookClientConfig
switch insideCluster {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.1
name: alertconfig.kimup.cloudavenue.io
name: alertconfigs.kimup.cloudavenue.io
spec:
group: kimup.cloudavenue.io
names:
kind: AlertConfig
listKind: AlertConfigList
plural: alertconfig
plural: alertconfigs
singular: alertconfig
scope: Namespaced
versions:
Expand Down
Empty file.
3 changes: 3 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ rules:
- apiGroups:
- kimup.cloudavenue.io
resources:
- alertconfigs
- images
verbs:
- create
Expand All @@ -19,12 +20,14 @@ rules:
- apiGroups:
- kimup.cloudavenue.io
resources:
- alertconfigs/finalizers
- images/finalizers
verbs:
- update
- apiGroups:
- kimup.cloudavenue.io
resources:
- alertconfigs/status
- images/status
verbs:
- get
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:gomoddirectives
module github.com/orange-cloudavenue/kube-image-updater

go 1.22.0
Expand Down Expand Up @@ -91,6 +92,7 @@ require (
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
Expand Down Expand Up @@ -118,6 +120,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/grpc v1.65.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down
6 changes: 3 additions & 3 deletions internal/actions/action_alert_discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func init() {

// Execute sends the alert message to the Discord channel.
func (a *alertDiscord) Execute(ctx context.Context) error {
alertConfig, err := a.k.GetValueOrValueFrom(ctx, a.Namespace, a.data)
alertConfig, err := a.k.GetValueOrValueFrom(ctx, a.image.Namespace, a.data)
if err != nil {
return err
}
Expand All @@ -52,12 +52,12 @@ func (a *alertDiscord) Execute(ctx context.Context) error {

sender, err := s.CreateSender(fmt.Sprintf("discord://%s@%s?splitlines=no", token, webhookID))
if err != nil {
return err
return fmt.Errorf("error creating Discord sender: %v", err)
}

message, err := a.Render()
if err != nil {
return err
return fmt.Errorf("error rendering alert message: %v", err)
}

log.Debugf("Sending Discord alert")
Expand Down
4 changes: 2 additions & 2 deletions internal/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type (
action struct {
tags models.Tags
image *v1alpha1.Image
k *kubeclient.Client
k kubeclient.Interface
data v1alpha1.ValueOrValueFrom
}
)
Expand Down Expand Up @@ -83,7 +83,7 @@ func GetActionWithUntypedName(name string) (models.ActionInterface, error) {

// * Generic action implementation

func (a *action) Init(kubeClient *kubeclient.Client, tags models.Tags, image *v1alpha1.Image, data v1alpha1.ValueOrValueFrom) {
func (a *action) Init(kubeClient kubeclient.Interface, tags models.Tags, image *v1alpha1.Image, data v1alpha1.ValueOrValueFrom) {
a.tags = tags
a.image = image
a.k = kubeClient
Expand Down
21 changes: 21 additions & 0 deletions internal/controller/alertconfig_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2024.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package controller

// +kubebuilder:rbac:groups=kimup.cloudavenue.io,resources=alertconfigs,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=kimup.cloudavenue.io,resources=alertconfigs/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=kimup.cloudavenue.io,resources=alertconfigs/finalizers,verbs=update
24 changes: 14 additions & 10 deletions internal/kubeclient/alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@ import (

type (
AlertObj struct {
c *Client
InterfaceKubernetes
alertClient dynamic.NamespaceableResourceInterface
}
)

// Alert() returns an alert object
func (c *Client) Alert() *AlertObj {
return NewAlert(c)
}

func NewAlert(k InterfaceKubernetes) *AlertObj {
return &AlertObj{
c: c,
alertClient: c.d.Resource(schema.GroupVersionResource{
InterfaceKubernetes: k,
alertClient: k.DynamicResource(schema.GroupVersionResource{
Group: v1alpha1.GroupVersion.Group,
Version: v1alpha1.GroupVersion.Version,
Resource: "alertconfig",
Resource: "alertconfigs",
}),
}
}
Expand All @@ -33,8 +37,8 @@ func (c *Client) Alert() *AlertObj {
// It takes a context, the namespace, and the name of the Alert as parameters.
// If the Alert is found, it returns a pointer to the Alert object and a nil error.
// If there is an error during the retrieval process, it returns nil and the error encountered.
func (a *AlertObj) Get(ctx context.Context, name string) (v1alpha1.AlertConfig, error) {
u, err := a.alertClient.Get(ctx, name, v1.GetOptions{})
func (a *AlertObj) Get(ctx context.Context, namespace, name string) (v1alpha1.AlertConfig, error) {
u, err := a.alertClient.Namespace(namespace).Get(ctx, name, v1.GetOptions{})
if err != nil {
return v1alpha1.AlertConfig{}, err
}
Expand All @@ -45,8 +49,8 @@ func (a *AlertObj) Get(ctx context.Context, name string) (v1alpha1.AlertConfig,
// List retrieves a list of AlertObj instances from the specified namespace.
// It takes a context, the namespace as a string, and list options.
// Returns a pointer to a List of AlertObj and an error if the operation fails.
func (a *AlertObj) List(ctx context.Context, opts v1.ListOptions) (v1alpha1.AlertConfigList, error) {
u, err := a.alertClient.List(ctx, opts)
func (a *AlertObj) List(ctx context.Context, namespace string, opts v1.ListOptions) (v1alpha1.AlertConfigList, error) {
u, err := a.alertClient.Namespace(namespace).List(ctx, opts)
if err != nil {
return v1alpha1.AlertConfigList{}, err
}
Expand All @@ -63,13 +67,13 @@ func (a *AlertObj) List(ctx context.Context, opts v1.ListOptions) (v1alpha1.Aler
//
// Returns:
// - An error if the update operation fails; otherwise, it returns nil.
func (a *AlertObj) Update(ctx context.Context, alert v1alpha1.AlertConfig) error {
func (a *AlertObj) Update(ctx context.Context, namespace string, alert v1alpha1.AlertConfig) error {
u, err := encodeUnstructured(alert)
if err != nil {
return err
}

_, err = a.alertClient.Update(ctx, u, v1.UpdateOptions{})
_, err = a.alertClient.Namespace(namespace).Update(ctx, u, v1.UpdateOptions{})
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit c640b95

Please sign in to comment.