-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement Update Deployment Image (#44)
* Chore [Language] Update Constants - [+] chore(init_const.go): add new error and success messages for updating deployment image - [+] feat(init_const.go): add new success message for updating deployment image * Feat [Worker] Update Deployment Image - [+] feat(worker): add UpdateDeploymentImage function to update deployment image - [+] feat(worker): add updateImageWithRetry function to retry updating image with conflict handling - [+] feat(worker): add updateDeploymentImageOnce function to update deployment image once - [+] feat(worker): add reportSuccess function to report successful image update - [+] feat(worker): add reportFailure function to report failed image update - [+] feat(worker): add reportMaxRetriesFailure function to report failed image update after reaching max retries * Chore [Language] Update Constants - [+] chore(init_const.go): add missing error messages for required parameters - [+] feat(init_const.go): add new task for updating deployment image * Feat [Worker] [Task] Extract Parameter - [+] fix(worker): fix typo in constant name from deploymentName to deploYmentName - [+] feat(worker): add new constant contaInerName and newImAge - [+] feat(worker): add function extractDeploymentParameters to extract deployment parameters from map * Feat [Worker] [Task Crew] Update Deployment Image - [+] feat(worker): add support for updating image deployments - [+] fix(worker): fix typo in variable name 'deploymentName' - [+] fix(worker): fix typo in variable name 'deploYmentName' - [+] fix(worker): fix typo in variable name 'deploymentName' - [+] feat(worker): add support for updating image deployments * Go Docs [Worker] [Update Image] Update Documentation - [+] feat(worker): update package documentation to reflect new features and functions - [+] feat(worker): add UpdateDeploymentImage function to update the image of a container within a deployment - [+] feat(worker): add updateImageWithRetry function to handle retries on conflicts when updating deployment image - [+] feat(worker): add updateDeploymentImageOnce function to perform a single attempt to update the deployment image - [+] feat(worker): add reportSuccess function to send success message and log success when updating deployment image - [+] feat(worker): add reportFailure function to send error message and log failure when updating deployment image - [+] feat(worker): add reportMaxRetriesFailure function to send message and log failure after reaching maximum number of retries when updating deployment image - [+] feat(worker): add extractDeploymentParameters function to extract and validate deploymentName, containerName, and newImage from parameters map
- Loading branch information
1 parent
cecf8d9
commit 627bdb3
Showing
6 changed files
with
250 additions
and
28 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
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 worker | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/H0llyW00dzZ/K8sBlackPearl/language" | ||
"github.com/H0llyW00dzZ/K8sBlackPearl/navigator" | ||
"github.com/H0llyW00dzZ/go-urlshortner/logmonitor/constant" | ||
"go.uber.org/zap" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
"k8s.io/client-go/util/retry" | ||
) | ||
|
||
// UpdateDeploymentImage attempts to update the image of a specified container within a deployment in Kubernetes. | ||
// It performs retries on conflicts and reports the outcome through a results channel. If the image update is successful, | ||
// a success message is sent to the results channel. In case of errors other than conflicts or after exceeding the maximum | ||
// number of retries, it reports the failure. | ||
// | ||
// Parameters: | ||
// - ctx: Context for cancellation and timeout. | ||
// - clientset: A Kubernetes clientset to interact with the Kubernetes API. | ||
// - namespace: The Kubernetes namespace containing the deployment. | ||
// - deploymentName: The name of the deployment to update. | ||
// - containerName: The name of the container within the deployment to update. | ||
// - newImage: The new image to apply to the container. | ||
// - results: A channel to send operation results for logging. | ||
// - logger: A logger for structured logging. | ||
// | ||
// Returns an error if the operation fails after the maximum number of retries or if a non-conflict error is encountered. | ||
func UpdateDeploymentImage(ctx context.Context, clientset *kubernetes.Clientset, namespace, deploymentName, containerName, newImage string, results chan<- string, logger *zap.Logger) error { | ||
for attempt := 0; attempt < maxRetries; attempt++ { | ||
err := updateImageWithRetry(ctx, clientset, namespace, deploymentName, containerName, newImage) | ||
if err == nil { | ||
reportSuccess(results, logger, deploymentName, newImage) | ||
return nil | ||
} | ||
|
||
if !errors.IsConflict(err) { | ||
reportFailure(results, logger, deploymentName, newImage, err) | ||
return err | ||
} | ||
|
||
navigator.LogInfoWithEmoji(language.SwordEmoji, fmt.Sprintf(language.ErrorConflictUpdateImage, deploymentName)) | ||
time.Sleep(retryDelay) | ||
} | ||
|
||
reportMaxRetriesFailure(results, logger, deploymentName, newImage) | ||
return fmt.Errorf(language.ErrorReachedMaxRetries) | ||
} | ||
|
||
// updateImageWithRetry attempts to update the deployment image, retrying on conflicts. | ||
// It uses the Kubernetes client-go utility 'RetryOnConflict' to handle retries. | ||
// | ||
// This function is unexported and used internally by UpdateDeploymentImage. | ||
func updateImageWithRetry(ctx context.Context, clientset *kubernetes.Clientset, namespace, deploymentName, containerName, newImage string) error { | ||
return retry.RetryOnConflict(retry.DefaultRetry, func() error { | ||
return updateDeploymentImageOnce(ctx, clientset, namespace, deploymentName, containerName, newImage) | ||
}) | ||
} | ||
|
||
// updateDeploymentImageOnce performs a single attempt to update the deployment image. | ||
// It fetches the current deployment, updates the image for the specified container, and applies the changes. | ||
// | ||
// This function is unexported and used internally by updateImageWithRetry. | ||
func updateDeploymentImageOnce(ctx context.Context, clientset *kubernetes.Clientset, namespace, deploymentName, containerName, newImage string) error { | ||
deployment, err := clientset.AppsV1().Deployments(namespace).Get(ctx, deploymentName, v1.GetOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for i, container := range deployment.Spec.Template.Spec.Containers { | ||
if container.Name == containerName { | ||
deployment.Spec.Template.Spec.Containers[i].Image = newImage | ||
break | ||
} | ||
} | ||
|
||
_, err = clientset.AppsV1().Deployments(namespace).Update(ctx, deployment, v1.UpdateOptions{}) | ||
return err | ||
} | ||
|
||
// reportSuccess sends a success message to the results channel and logs the success. | ||
// | ||
// This function is unexported and used internally by UpdateDeploymentImage. | ||
func reportSuccess(results chan<- string, logger *zap.Logger, deploymentName, newImage string) { | ||
successMsg := fmt.Sprintf(language.ImageSuccessfully, deploymentName, newImage) | ||
results <- successMsg | ||
navigator.LogInfoWithEmoji(constant.SuccessEmoji, successMsg) | ||
} | ||
|
||
// reportFailure sends an error message to the results channel and logs the failure. | ||
// | ||
// This function is unexported and used internally by UpdateDeploymentImage. | ||
func reportFailure(results chan<- string, logger *zap.Logger, deploymentName, newImage string, err error) { | ||
errorMessage := fmt.Sprintf(language.ErrorFailedToUpdateImage, deploymentName, err) | ||
results <- errorMessage | ||
navigator.LogErrorWithEmojiRateLimited(constant.ErrorEmoji, errorMessage) | ||
} | ||
|
||
// reportMaxRetriesFailure sends a message to the results channel and logs the failure after reaching the maximum number of retries. | ||
// | ||
// This function is unexported and used internally by UpdateDeploymentImage. | ||
func reportMaxRetriesFailure(results chan<- string, logger *zap.Logger, deploymentName, newImage string) { | ||
failMessage := fmt.Sprintf(language.ErrorFailedToUpdateImageAfterRetries, deploymentName, maxRetries) | ||
results <- failMessage | ||
navigator.LogErrorWithEmojiRateLimited(constant.ErrorEmoji, failMessage) | ||
} | ||
|
||
// extractDeploymentParameters extracts and validates the deploymentName, containerName, and newImage from a map of parameters. | ||
// It returns an error if any of the parameters are missing or not a string type. | ||
// | ||
// This function is unexported and used internally by other functions within the package. | ||
func extractDeploymentParameters(parameters map[string]interface{}) (deploymentName, containerName, newImage string, err error) { | ||
var ok bool | ||
if deploymentName, ok = parameters[deploYmentName].(string); !ok { | ||
err = fmt.Errorf(language.ErrorParameterDeploymentName) | ||
return | ||
} | ||
if containerName, ok = parameters[contaInerName].(string); !ok { | ||
err = fmt.Errorf(language.ErrorParameterContainerName) | ||
return | ||
} | ||
if newImage, ok = parameters[newImAge].(string); !ok { | ||
err = fmt.Errorf(language.ErrorParameterNewImage) | ||
return | ||
} | ||
return | ||
} |