-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add check if knuu was initialized Signed-off-by: Smuu <18609909+Smuu@users.noreply.github.com> * feat: add preloader Signed-off-by: Smuu <18609909+Smuu@users.noreply.github.com> --------- Signed-off-by: Smuu <18609909+Smuu@users.noreply.github.com>
- Loading branch information
Showing
5 changed files
with
298 additions
and
8 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package k8s | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/sirupsen/logrus" | ||
appv1 "k8s.io/api/apps/v1" | ||
v1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"time" | ||
) | ||
|
||
// DaemonSetExists checks if a daemonset exists. | ||
func DaemonSetExists(namespace, name string) (bool, error) { | ||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
if !IsInitialized() { | ||
return false, fmt.Errorf("knuu is not initialized") | ||
} | ||
_, err := Clientset().AppsV1().DaemonSets(namespace).Get(ctx, name, metav1.GetOptions{}) | ||
if err != nil { | ||
if isNotFound(err) { | ||
return false, nil | ||
} | ||
return false, fmt.Errorf("error getting daemonset %s: %w", name, err) | ||
} | ||
return true, nil | ||
} | ||
|
||
// GetDaemonSet retrieves a daemonset. | ||
func GetDaemonSet(namespace, name string) (*appv1.DaemonSet, error) { | ||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
if !IsInitialized() { | ||
return nil, fmt.Errorf("knuu is not initialized") | ||
} | ||
ds, err := Clientset().AppsV1().DaemonSets(namespace).Get(ctx, name, metav1.GetOptions{}) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting daemonset %s: %w", name, err) | ||
} | ||
return ds, nil | ||
} | ||
|
||
// CreateDaemonSet creates a new daemonset. | ||
func CreateDaemonSet(namespace, name string, labels map[string]string, initContainers []v1.Container, containers []v1.Container) (*appv1.DaemonSet, error) { | ||
|
||
ds, err := prepareDaemonSet(namespace, name, labels, initContainers, containers) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
if !IsInitialized() { | ||
return nil, fmt.Errorf("knuu is not initialized") | ||
} | ||
created, err := Clientset().AppsV1().DaemonSets(namespace).Create(ctx, ds, metav1.CreateOptions{}) | ||
if err != nil { | ||
return nil, fmt.Errorf("error creating daemonset %s: %w", name, err) | ||
} | ||
logrus.Debugf("DaemonSet %s created in namespace %s", name, namespace) | ||
return created, nil | ||
} | ||
|
||
// UpdateDaemonSet updates an existing daemonset. | ||
func UpdateDaemonSet(namespace, name string, labels map[string]string, initContainers []v1.Container, containers []v1.Container) (*appv1.DaemonSet, error) { | ||
|
||
ds, err := prepareDaemonSet(namespace, name, labels, initContainers, containers) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
if !IsInitialized() { | ||
return nil, fmt.Errorf("knuu is not initialized") | ||
} | ||
updated, err := Clientset().AppsV1().DaemonSets(namespace).Update(ctx, ds, metav1.UpdateOptions{}) | ||
if err != nil { | ||
return nil, fmt.Errorf("error updating daemonset %s: %w", name, err) | ||
} | ||
logrus.Debugf("DaemonSet %s updated in namespace %s", name, namespace) | ||
return updated, nil | ||
} | ||
|
||
// DeleteDaemonSet deletes an existing daemonset. | ||
func DeleteDaemonSet(namespace, name string) error { | ||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
if !IsInitialized() { | ||
return fmt.Errorf("knuu is not initialized") | ||
} | ||
if err := Clientset().AppsV1().DaemonSets(namespace).Delete(ctx, name, metav1.DeleteOptions{}); err != nil { | ||
return fmt.Errorf("error deleting daemonset %s: %w", name, err) | ||
} | ||
logrus.Debugf("DaemonSet %s deleted in namespace %s", name, namespace) | ||
return nil | ||
} | ||
|
||
// prepareService constructs a new Service object with the specified parameters. | ||
func prepareDaemonSet(namespace, name string, labels map[string]string, initContainers []v1.Container, containers []v1.Container) (*appv1.DaemonSet, error) { | ||
|
||
ds := &appv1.DaemonSet{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
Labels: labels, | ||
}, | ||
Spec: appv1.DaemonSetSpec{ | ||
Selector: &metav1.LabelSelector{ | ||
MatchLabels: labels, | ||
}, | ||
Template: v1.PodTemplateSpec{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Labels: labels, | ||
}, | ||
Spec: v1.PodSpec{ | ||
InitContainers: initContainers, | ||
Containers: containers, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
return ds, nil | ||
|
||
} |
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,107 @@ | ||
package knuu | ||
|
||
import ( | ||
"fmt" | ||
"github.com/celestiaorg/knuu/pkg/k8s" | ||
v1 "k8s.io/api/core/v1" | ||
) | ||
|
||
// Preloader is a struct that contains the list of preloaded images. | ||
// A preloader makes sure that the images are preloaded before the test suite starts. | ||
// Hint: If you use a Preloader per test suite, you can save resources | ||
type Preloader struct { | ||
k8sName string `json:"k8sName"` | ||
images []string `json:"images"` | ||
} | ||
|
||
// NewPreloader creates a new preloader | ||
func NewPreloader() (*Preloader, error) { | ||
k8sName, err := generateK8sName("knuu-preloader") | ||
if err != nil { | ||
return nil, fmt.Errorf("error generating k8s name for preloader: %w", err) | ||
} | ||
return &Preloader{ | ||
k8sName: k8sName, | ||
images: []string{}, | ||
}, nil | ||
} | ||
|
||
// Images returns the list of preloaded images | ||
func (p *Preloader) Images() []string { | ||
return p.images | ||
} | ||
|
||
// AddImage adds an image to the list of preloaded images | ||
func (p *Preloader) AddImage(image string) error { | ||
// dont add duplicates | ||
for _, v := range p.images { | ||
if v == image { | ||
return nil | ||
} | ||
} | ||
p.images = append(p.images, image) | ||
return p.preloadImages() | ||
} | ||
|
||
// RemoveImage removes an image from the list of preloaded images | ||
func (p *Preloader) RemoveImage(image string) error { | ||
for i, v := range p.images { | ||
if v == image { | ||
p.images = append(p.images[:i], p.images[i+1:]...) | ||
} | ||
} | ||
return p.preloadImages() | ||
} | ||
|
||
// EmptyImages empties the list of preloaded images | ||
func (p *Preloader) EmptyImages() error { | ||
p.images = []string{} | ||
return p.preloadImages() | ||
} | ||
|
||
// preloadImages preloads all images in the list of preloaded images | ||
func (p *Preloader) preloadImages() error { | ||
// delete the daemonset if no images are preloaded | ||
if len(p.images) == 0 { | ||
return k8s.DeleteDaemonSet(k8s.Namespace(), p.k8sName) | ||
} | ||
var initContainers []v1.Container | ||
|
||
for i, image := range p.images { | ||
initContainers = append(initContainers, v1.Container{ | ||
Name: fmt.Sprintf("image%d-preloader", i), | ||
Image: image, | ||
Command: []string{ | ||
"/bin/sh", | ||
"-c", | ||
"exit 0", | ||
}, | ||
}) | ||
} | ||
|
||
var containers []v1.Container | ||
|
||
containers = append(containers, v1.Container{ | ||
Name: "pause-container", | ||
Image: "k8s.gcr.io/pause", | ||
}) | ||
|
||
labels := map[string]string{ | ||
"app": p.k8sName, | ||
} | ||
|
||
exists, err := k8s.DaemonSetExists(k8s.Namespace(), p.k8sName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// update the daemonset if it already exists | ||
if exists { | ||
_, err = k8s.UpdateDaemonSet(k8s.Namespace(), p.k8sName, labels, initContainers, containers) | ||
return err | ||
} | ||
|
||
// create the daemonset if it doesn't exist | ||
_, err = k8s.CreateDaemonSet(k8s.Namespace(), p.k8sName, labels, initContainers, containers) | ||
return err | ||
} |