Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Crew Creating PVC Storage #49

Merged
merged 5 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions language/init_const.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ const (
ErrorParameterReplicas = "parameter 'replicas' is required and must be an integer"
ErrorParameterNewImage = "parameter 'newImage' is required and must be a string"
ErrorParameterContainerName = "parameter 'containerName' is required and must be a string"
ErrorParameterStorageClassName = "parameter 'storageClassName' is required and must be a string"
ErrorParameterpvcName = "parameter 'pvcName' is required and must be a string"
ErrorparameterstorageSize = "parameter 'storageSize' is required and must be a string"
ErrorConflict = "Conflict detected when scaling deployment '%s', resolving..."
FailedToScaleDeployment = "Failed to scale deployment '%s' to '%d' after %d retries: %v"
FailedTOScallEdDeployment = "Failed to scale deployment '%s' to '%d': %v"
Expand All @@ -49,6 +52,9 @@ const (
ErrorFailedToUpdateImage = "Failed to update image for deployment %s: %v"
ErrorFailedToUpdateImageAfterRetries = "Failed to update image for deployment %s after %d retries"
ErrorFailedToUpdateDeployImage = "Failed to update deployment image"
ErrorCreatingPvc = "Error creating pvc: %w"
ErrorCreatingStorageClass = "Error creating storage class: %w"
ErrorFailedToCreatePvc = "Failed to create PVC '%s': %v"
)

const (
Expand Down Expand Up @@ -86,9 +92,11 @@ const (
TaskManageDeployments = "ManageDeployments"
TaskScaleDeployment = "ScaleDeployment"
TaskUpdateDeploymentImage = "UpdateDeploymentImage"
TaskCreatePVC = "CreatePVCStorage"
ScalingDeployment = "Crew Worker %d: Scaling deployments"
ManagingDeployments = "Crew Worker %d: Managing deployments"
UpdatingImage = "Crew Worker %d: Updating deployment image"
CreatePVCStorage = "Crew Worker %d: Creating PVC storage"
)

const (
Expand All @@ -108,6 +116,7 @@ const (
ImageSuccessfully = "Image updated successfully for deployment %s to %s"
DeploymentImageUpdated = "Deployment image updated successfully"
UpdatingDeploymentImage = "Updating deployment image"
WorkerSucessfullyCreatePVC = "Successfully created PVC '%s' in namespace '%s'"
)

const (
Expand Down
29 changes: 16 additions & 13 deletions worker/cmd_constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,22 @@ const (

// defined object
const (
metaData = "metadata"
labeLs = "labels"
labeLKey = "labelKey"
labeLValue = "labelValue"
labelSelector = "labelSelector"
fieldSelector = "fieldSelector"
limIt = "limit"
deploYmentName = "deploymentName"
contaInerName = "containerName"
newImAge = "newImage"
repliCas = "replicas"
deploymenT = "deployment"
scalE = "scale"
metaData = "metadata"
labeLs = "labels"
labeLKey = "labelKey"
labeLValue = "labelValue"
labelSelector = "labelSelector"
fieldSelector = "fieldSelector"
limIt = "limit"
deploYmentName = "deploymentName"
contaInerName = "containerName"
newImAge = "newImage"
repliCas = "replicas"
deploymenT = "deployment"
scalE = "scale"
storageClassName = "storageClassName"
pvcName = "pvcName"
storageSize = "storageSize"
)

// defined notice message just like human would type
Expand Down
27 changes: 20 additions & 7 deletions worker/docs.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Package worker provides a set of tools designed to facilitate the interaction with
// Kubernetes resources from within a cluster. It offers a convenient abstraction for
// managing Kubernetes operations, focusing on pod health checks, pod labeling, structured logging,
// scaling deployments, updating deployment images, and task configuration through YAML or JSON files.
// scaling deployments, updating deployment images, creating PersistentVolumeClaims (PVCs),
// and task configuration through YAML or JSON files.
//
// The package is intended for applications running as pods within Kubernetes clusters
// and leverages in-cluster configuration to establish a clientset for API interactions.
Expand Down Expand Up @@ -31,21 +32,26 @@
// within deployments. This includes handling retries on update conflicts and reporting
// the outcome of the operation.
//
// - Creation of PersistentVolumeClaims (PVCs) is now supported, allowing for dynamic
// provisioning of storage resources within the cluster. The process is logged with
// emojis to indicate success or failure, improving the visibility of the operation's outcome.
//
// # Functions
//
// - NewKubernetesClient: Creates a new Kubernetes clientset configured for in-cluster
// communication with the Kubernetes API server.
//
// - CrewWorker: Orchestrates a worker process to perform tasks such as health checks,
// labeling of pods, scaling deployments, updating deployment images, and other configurable tasks within a specified namespace.
// labeling of pods, scaling deployments, updating deployment images, creating PVCs,
// and other configurable tasks within a specified namespace.
// It includes retry logic to handle transient errors and respects cancellation and timeout contexts.
// Structured logging is used to provide detailed contextual information.
// Structured logging is used to provide detailed contextual information, now with emojis for better visual cues.
//
// - LoadTasksFromYAML: Loads task configurations from a YAML file, allowing for
// dynamic task management based on external configuration.
//
// - CrewGetPods: Retrieves all pods within a given namespace, logging the attempt
// and outcome of the operation.
// and outcome of the operation, now with emojis for quick status recognition.
//
// - CrewProcessPods: Iterates over a collection of pods, assessing their health,
// updating labels, and reporting the status to a results channel. It also handles context cancellation.
Expand All @@ -63,11 +69,15 @@
// - UpdateDeploymentImage: Updates the image of a specified container within a deployment,
// handling retries on conflicts and reporting the outcome through a results channel.
//
// - CrewCreatePVCStorage: Creates a PersistentVolumeClaim in the specified namespace,
// allowing for storage provisioning according to the parameters provided.
// The creation process is logged with success and error emojis for immediate feedback.
//
// Usage:
//
// Initialize the Kubernetes client using NewKubernetesClient, then leverage the client
// to perform operations such as retrieving and processing pods within a namespace, scaling
// deployments, and updating deployment images as required. Contexts are used to manage the
// deployments, updating deployment images, and creating PVCs as required. Contexts are used to manage the
// lifecycle of the worker processes, including graceful shutdowns and cancellation. Task
// configurations can be loaded from a YAML file for enhanced flexibility.
//
Expand Down Expand Up @@ -96,11 +106,11 @@
//
// # Enhancements
//
// - The package now includes structured logging capabilities, enhancing traceability
// - The package now includes structured logging capabilities, enhanced with emojis, improving traceability
// and aiding in debugging efforts by providing detailed contextual information.
//
// - Logging functionality is customizable, allowing different workers to provide
// unique contextual information, such as worker indices or specific namespaces.
// unique contextual information, such as worker indices or specific namespaces, with visual cues.
//
// - The dynamic task execution model supports adding new tasks and task runners
// without changing existing code, facilitating scalability and extensibility.
Expand All @@ -114,6 +124,9 @@
// - Image update functionality has been added to modify the image of a container within
// a deployment, with built-in retry logic for handling update conflicts.
//
// - The introduction of PVC creation allows for dynamic storage provisioning, complete with
// emoji-based logging for immediate operation feedback.
//
// # TODO
//
// - Extend the functionality of the CrewWorker function to support a wider range
Expand Down
3 changes: 3 additions & 0 deletions worker/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ func init() {
// Register the new TaskRunner for updating image deployments.
RegisterTaskRunner("CrewUpdateImageDeployments", func() TaskRunner { return &CrewUpdateImageDeployments{} })

// Register the new TaskRunner for create storage pvc
RegisterTaskRunner("CrewCreatePVCStorage", func() TaskRunner { return &CrewCreatePVCStorage{} })

}
54 changes: 54 additions & 0 deletions worker/pvc_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package worker

import (
"context"
"fmt"

"github.com/H0llyW00dzZ/K8sBlackPearl/language"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

// createPVC creates a persistent volume claim (PVC) in the specified namespace.
//
// Parameters:
// - ctx: Context for cancellation and timeout.
// - clientset: A Kubernetes clientset to interact with the Kubernetes API.
// - shipsNamespace: The Kubernetes namespace in which to create the PVC.
// - storageClassName: The name of the storage class to use for the PVC.
// - pvcName: The name of the PVC to create.
// - storageSize: The size of the PVC in gigabytes.
//
// Returns an error if the PVC cannot be created.
func createPVC(ctx context.Context, clientset *kubernetes.Clientset, shipsNamespace, storageClassName, pvcName, storageSize string) error {
// Define the PVC object.
pvc := &corev1.PersistentVolumeClaim{
ObjectMeta: v1.ObjectMeta{
Name: pvcName,
},
Spec: corev1.PersistentVolumeClaimSpec{
// Specify the storage class to use.
StorageClassName: &storageClassName,
// Request read/write access to the PVC.
AccessModes: []corev1.PersistentVolumeAccessMode{
corev1.ReadWriteOnce,
},
// Define the requested storage size.
Resources: corev1.VolumeResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse(storageSize),
},
},
},
}

// Create the PVC using the Kubernetes API.
_, err := clientset.CoreV1().PersistentVolumeClaims(shipsNamespace).Create(ctx, pvc, v1.CreateOptions{})
if err != nil {
return fmt.Errorf(language.ErrorCreatingPvc, err)
}

return nil
}
64 changes: 64 additions & 0 deletions worker/tasks_crew.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,70 @@ func (c *CrewUpdateImageDeployments) Run(ctx context.Context, clientset *kuberne
return nil
}

// CrewCreatePVCStorage is an implementation of TaskRunner that creates a PersistentVolumeClaim.
//
// This struct is responsible for creating PVCs (PersistentVolumeClaims) in a Kubernetes cluster.
// It extracts the necessary parameters from the task parameters, calls the createPVC function to create the PVC,
// and handles logging and error handling during the process.
type CrewCreatePVCStorage struct {
// shipsNamespace specifies the Kubernetes namespace where the PVC will be created.
shipsNamespace string

// workerIndex is an identifier for the worker that is executing the task.
// This can be used for logging and tracking the progress of the task across multiple workers.
workerIndex int
}

// Run creates a PersistentVolumeClaim in the specified namespace using the provided parameters.
//
// This method orchestrates the task execution by extracting the required parameters,
// invoking the createPVC function to create the PVC, and handling any errors or logging messages.
func (c *CrewCreatePVCStorage) Run(ctx context.Context, clientset *kubernetes.Clientset, shipsNamespace string, taskName string, parameters map[string]interface{}, workerIndex int) error {
// Define logging fields for structured logging
fields := navigator.CreateLogFields(
language.TaskCreatePVC,
shipsNamespace,
navigator.WithAnyZapField(zap.String(language.Task_Name, taskName)),
)

// Log the start of the PVC creation operation
navigator.LogInfoWithEmoji(
language.PirateEmoji,
fmt.Sprintf(language.CreatePVCStorage, workerIndex),
fields...,
)

// Extract the necessary parameters from the task parameters
storageClassName, ok := parameters[storageClassName].(string)
if !ok {
return fmt.Errorf(language.ErrorParameterStorageClassName)
}
pvcName, ok := parameters[pvcName].(string)
if !ok {
return fmt.Errorf(language.ErrorParameterpvcName)
}
storageSize, ok := parameters[storageSize].(string)
if !ok {
return fmt.Errorf(language.ErrorparameterstorageSize)
}

// Call the createPVC function with the extracted parameters to create the PVC
err := createPVC(ctx, clientset, shipsNamespace, storageClassName, pvcName, storageSize)
if err != nil {
// Log the error and return
errorFields := append(fields, zap.String(language.Error, err.Error()))
failedMessage := fmt.Sprintf(language.ErrorFailedToCreatePvc, pvcName, err)
navigator.LogErrorWithEmojiRateLimited(constant.ErrorEmoji, failedMessage, errorFields...)
return err
}

// Log the successful creation of the PVC
successMessage := fmt.Sprintf(language.WorkerSucessfullyCreatePVC, pvcName, shipsNamespace)
navigator.LogInfoWithEmoji(constant.SuccessEmoji, successMessage, fields...)

return nil
}

// getLatestVersionOfPod fetches the latest version of the Pod from the Kubernetes API.
func getLatestVersionOfPod(ctx context.Context, clientset *kubernetes.Clientset, namespace string, podName string) (*corev1.Pod, error) {
// Fetch the latest version of the Pod using the clientset.
Expand Down