mirror of
https://github.com/stakater/Reloader.git
synced 2026-02-14 18:09:50 +00:00
176 - Add reload strategies to support pod annotation templates
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,4 +8,5 @@ _gopath/
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode
|
.vscode
|
||||||
vendor
|
vendor
|
||||||
dist
|
dist
|
||||||
|
Reloader
|
||||||
13
README.md
13
README.md
@@ -145,6 +145,19 @@ spec:
|
|||||||
- you may want to prevent watching certain namespaces with the `--namespaces-to-ignore` flag
|
- you may want to prevent watching certain namespaces with the `--namespaces-to-ignore` flag
|
||||||
- you may want to prevent watching certain resources with the `--resources-to-ignore` flag
|
- you may want to prevent watching certain resources with the `--resources-to-ignore` flag
|
||||||
- you can configure logging in JSON format with the `--log-format=json` option
|
- you can configure logging in JSON format with the `--log-format=json` option
|
||||||
|
- you can configure the "reload strategy" with the `--reload-strategy=<strategy-name>` option (details below)
|
||||||
|
|
||||||
|
## Reload Strategies
|
||||||
|
Reloader supports multiple "reload" strategies for performing rolling upgrades to resources. The following list describes them:
|
||||||
|
- **env-vars**: When a tracked `configMap`/`secret` is updated, this strategy attaches a Reloader specific environment variable to any containers
|
||||||
|
referencing the changed `configMap` or `secret` on the owning resource (e.g., `Deployment`, `StatefulSet`, etc.).
|
||||||
|
This strategy can be specified with the `--reload-strategy=env-vars` argument. Note: This is the default reload strategy.
|
||||||
|
- **annotations**: When a tracked `configMap`/`secret` is updated, this strategy attaches a `reloader.stakater.com/last-reloaded-from` pod template annotation
|
||||||
|
on the owning resource (e.g., `Deployment`, `StatefulSet`, etc.). This strategy is useful when using resource syncing tools like ArgoCD, since it will not cause these tools
|
||||||
|
to detect configuration drift after a resource is reloaded. Note: Since the attached pod template annotation only tracks the last reload source, this strategy will reload any tracked resource should its
|
||||||
|
`configMap` or `secret` be deleted and recreated.
|
||||||
|
This strategy can be specified with the `--reload-strategy=annotations` argument.
|
||||||
|
|
||||||
|
|
||||||
## Deploying to Kubernetes
|
## Deploying to Kubernetes
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ func GetDeploymentItems(clients kube.Clients, namespace string) []interface{} {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to list deployments %v", err)
|
logrus.Errorf("Failed to list deployments %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we always have pod annotations to add to
|
||||||
|
for i, v := range deployments.Items {
|
||||||
|
if v.Spec.Template.ObjectMeta.Annotations == nil {
|
||||||
|
annotations := make(map[string]string)
|
||||||
|
deployments.Items[i].Spec.Template.ObjectMeta.Annotations = annotations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.InterfaceSlice(deployments.Items)
|
return util.InterfaceSlice(deployments.Items)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +70,14 @@ func GetDaemonSetItems(clients kube.Clients, namespace string) []interface{} {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to list daemonSets %v", err)
|
logrus.Errorf("Failed to list daemonSets %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we always have pod annotations to add to
|
||||||
|
for i, v := range daemonSets.Items {
|
||||||
|
if v.Spec.Template.ObjectMeta.Annotations == nil {
|
||||||
|
daemonSets.Items[i].Spec.Template.ObjectMeta.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.InterfaceSlice(daemonSets.Items)
|
return util.InterfaceSlice(daemonSets.Items)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +87,14 @@ func GetStatefulSetItems(clients kube.Clients, namespace string) []interface{} {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to list statefulSets %v", err)
|
logrus.Errorf("Failed to list statefulSets %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we always have pod annotations to add to
|
||||||
|
for i, v := range statefulSets.Items {
|
||||||
|
if v.Spec.Template.ObjectMeta.Annotations == nil {
|
||||||
|
statefulSets.Items[i].Spec.Template.ObjectMeta.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.InterfaceSlice(statefulSets.Items)
|
return util.InterfaceSlice(statefulSets.Items)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +104,14 @@ func GetDeploymentConfigItems(clients kube.Clients, namespace string) []interfac
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to list deploymentConfigs %v", err)
|
logrus.Errorf("Failed to list deploymentConfigs %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we always have pod annotations to add to
|
||||||
|
for i, v := range deploymentConfigs.Items {
|
||||||
|
if v.Spec.Template.ObjectMeta.Annotations == nil {
|
||||||
|
deploymentConfigs.Items[i].Spec.Template.ObjectMeta.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.InterfaceSlice(deploymentConfigs.Items)
|
return util.InterfaceSlice(deploymentConfigs.Items)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +121,14 @@ func GetRolloutItems(clients kube.Clients, namespace string) []interface{} {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to list Rollouts %v", err)
|
logrus.Errorf("Failed to list Rollouts %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we always have pod annotations to add to
|
||||||
|
for i, v := range rollouts.Items {
|
||||||
|
if v.Spec.Template.ObjectMeta.Annotations == nil {
|
||||||
|
rollouts.Items[i].Spec.Template.ObjectMeta.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.InterfaceSlice(rollouts.Items)
|
return util.InterfaceSlice(rollouts.Items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/stakater/Reloader/internal/pkg/constants"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -18,9 +20,10 @@ import (
|
|||||||
// NewReloaderCommand starts the reloader controller
|
// NewReloaderCommand starts the reloader controller
|
||||||
func NewReloaderCommand() *cobra.Command {
|
func NewReloaderCommand() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "reloader",
|
Use: "reloader",
|
||||||
Short: "A watcher for your Kubernetes cluster",
|
Short: "A watcher for your Kubernetes cluster",
|
||||||
Run: startReloader,
|
PreRunE: validateFlags,
|
||||||
|
Run: startReloader,
|
||||||
}
|
}
|
||||||
|
|
||||||
// options
|
// options
|
||||||
@@ -33,9 +36,24 @@ func NewReloaderCommand() *cobra.Command {
|
|||||||
cmd.PersistentFlags().StringSlice("resources-to-ignore", []string{}, "list of resources to ignore (valid options 'configMaps' or 'secrets')")
|
cmd.PersistentFlags().StringSlice("resources-to-ignore", []string{}, "list of resources to ignore (valid options 'configMaps' or 'secrets')")
|
||||||
cmd.PersistentFlags().StringSlice("namespaces-to-ignore", []string{}, "list of namespaces to ignore")
|
cmd.PersistentFlags().StringSlice("namespaces-to-ignore", []string{}, "list of namespaces to ignore")
|
||||||
cmd.PersistentFlags().StringVar(&options.IsArgoRollouts, "is-Argo-Rollouts", "false", "Add support for argo rollouts")
|
cmd.PersistentFlags().StringVar(&options.IsArgoRollouts, "is-Argo-Rollouts", "false", "Add support for argo rollouts")
|
||||||
|
cmd.PersistentFlags().StringVar(&options.ReloadStrategy, constants.ReloadStrategyFlag, constants.EnvVarsReloadStrategy, "Specifies the desired reload strategy")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateFlags(*cobra.Command, []string) error {
|
||||||
|
// Ensure the reload strategy is one of the following...
|
||||||
|
valid := []string{constants.EnvVarsReloadStrategy, constants.AnnotationsReloadStrategy}
|
||||||
|
for _, s := range valid {
|
||||||
|
if s == options.ReloadStrategy {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := fmt.Sprintf("%s must be one of: %s", constants.ReloadStrategyFlag, strings.Join(valid, ", "))
|
||||||
|
return errors.New(err)
|
||||||
|
}
|
||||||
|
|
||||||
func configureLogging(logFormat string) error {
|
func configureLogging(logFormat string) error {
|
||||||
switch logFormat {
|
switch logFormat {
|
||||||
case "json":
|
case "json":
|
||||||
|
|||||||
@@ -7,4 +7,16 @@ const (
|
|||||||
SecretEnvVarPostfix = "SECRET"
|
SecretEnvVarPostfix = "SECRET"
|
||||||
// EnvVarPrefix is a Prefix for environment variable
|
// EnvVarPrefix is a Prefix for environment variable
|
||||||
EnvVarPrefix = "STAKATER_"
|
EnvVarPrefix = "STAKATER_"
|
||||||
|
|
||||||
|
// ReloaderAnnotationPrefix is a Prefix for all reloader annotations
|
||||||
|
ReloaderAnnotationPrefix = "reloader.stakater.com"
|
||||||
|
// LastReloadedFromAnnotation is an annotation used to describe the last resource that triggered a reload
|
||||||
|
LastReloadedFromAnnotation = "last-reloaded-from"
|
||||||
|
|
||||||
|
// ReloadStrategyFlag The reload strategy flag name
|
||||||
|
ReloadStrategyFlag = "reload-strategy"
|
||||||
|
// EnvVarsReloadStrategy instructs Reloader to add container environment variables to facilitate a restart
|
||||||
|
EnvVarsReloadStrategy = "env-vars"
|
||||||
|
// AnnotationsReloadStrategy instructs Reloader to add pod template annotations to facilitate a restart
|
||||||
|
AnnotationsReloadStrategy = "annotations"
|
||||||
)
|
)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"encoding/json"
|
||||||
"strings"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/stakater/Reloader/internal/pkg/callbacks"
|
"github.com/stakater/Reloader/internal/pkg/callbacks"
|
||||||
@@ -13,6 +13,8 @@ import (
|
|||||||
"github.com/stakater/Reloader/internal/pkg/util"
|
"github.com/stakater/Reloader/internal/pkg/util"
|
||||||
"github.com/stakater/Reloader/pkg/kube"
|
"github.com/stakater/Reloader/pkg/kube"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetDeploymentRollingUpgradeFuncs returns all callback funcs for a deployment
|
// GetDeploymentRollingUpgradeFuncs returns all callback funcs for a deployment
|
||||||
@@ -146,7 +148,7 @@ func PerformRollingUpgrade(clients kube.Clients, config util.Config, upgradeFunc
|
|||||||
result := constants.NotUpdated
|
result := constants.NotUpdated
|
||||||
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
|
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
|
||||||
if err == nil && reloaderEnabled {
|
if err == nil && reloaderEnabled {
|
||||||
result = updateContainers(upgradeFuncs, i, config, true)
|
result = invokeReloadStrategy(upgradeFuncs, i, config, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result != constants.Updated && annotationValue != "" {
|
if result != constants.Updated && annotationValue != "" {
|
||||||
@@ -154,7 +156,7 @@ func PerformRollingUpgrade(clients kube.Clients, config util.Config, upgradeFunc
|
|||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
value = strings.Trim(value, " ")
|
value = strings.Trim(value, " ")
|
||||||
if value == config.ResourceName {
|
if value == config.ResourceName {
|
||||||
result = updateContainers(upgradeFuncs, i, config, false)
|
result = invokeReloadStrategy(upgradeFuncs, i, config, false)
|
||||||
if result == constants.Updated {
|
if result == constants.Updated {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -165,7 +167,7 @@ func PerformRollingUpgrade(clients kube.Clients, config util.Config, upgradeFunc
|
|||||||
if result != constants.Updated && searchAnnotationValue == "true" {
|
if result != constants.Updated && searchAnnotationValue == "true" {
|
||||||
matchAnnotationValue := config.ResourceAnnotations[options.SearchMatchAnnotation]
|
matchAnnotationValue := config.ResourceAnnotations[options.SearchMatchAnnotation]
|
||||||
if matchAnnotationValue == "true" {
|
if matchAnnotationValue == "true" {
|
||||||
result = updateContainers(upgradeFuncs, i, config, true)
|
result = invokeReloadStrategy(upgradeFuncs, i, config, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +259,7 @@ func getContainerWithEnvReference(containers []v1.Container, resourceName string
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainerToUpdate(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) *v1.Container {
|
func getContainerUsingResource(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) *v1.Container {
|
||||||
volumes := upgradeFuncs.VolumesFunc(item)
|
volumes := upgradeFuncs.VolumesFunc(item)
|
||||||
containers := upgradeFuncs.ContainersFunc(item)
|
containers := upgradeFuncs.ContainersFunc(item)
|
||||||
initContainers := upgradeFuncs.InitContainersFunc(item)
|
initContainers := upgradeFuncs.InitContainersFunc(item)
|
||||||
@@ -296,10 +298,70 @@ func getContainerToUpdate(upgradeFuncs callbacks.RollingUpgradeFuncs, item inter
|
|||||||
return container
|
return container
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateContainers(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) constants.Result {
|
func invokeReloadStrategy(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) constants.Result {
|
||||||
|
if options.ReloadStrategy == constants.AnnotationsReloadStrategy {
|
||||||
|
return updatePodAnnotations(upgradeFuncs, item, config, autoReload)
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateContainerEnvVars(upgradeFuncs, item, config, autoReload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePodAnnotations(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) constants.Result {
|
||||||
|
container := getContainerUsingResource(upgradeFuncs, item, config, autoReload)
|
||||||
|
if container == nil {
|
||||||
|
return constants.NoContainerFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate reloaded annotations. Attaching this to the item's annotation will trigger a rollout
|
||||||
|
// Note: the data on this struct is purely informational and is not used for future updates
|
||||||
|
reloadSource := util.NewReloadSourceFromConfig(config, []string{container.Name})
|
||||||
|
annotations, err := createReloadedAnnotations(&reloadSource)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("Failed to create reloaded annotations for %s! error = %v", config.ResourceName, err)
|
||||||
|
return constants.NotUpdated
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the all annotations to the item's annotations
|
||||||
|
pa := upgradeFuncs.PodAnnotationsFunc(item)
|
||||||
|
if pa == nil {
|
||||||
|
return constants.NotUpdated
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range annotations {
|
||||||
|
pa[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return constants.Updated
|
||||||
|
}
|
||||||
|
|
||||||
|
func createReloadedAnnotations(target *util.ReloadSource) (map[string]string, error) {
|
||||||
|
if target == nil {
|
||||||
|
return nil, errors.New("target is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a single "last-invokeReloadStrategy-from" annotation that stores metadata about the
|
||||||
|
// resource that caused the last invokeReloadStrategy.
|
||||||
|
// Intentionally only storing the last item in order to keep
|
||||||
|
// the generated annotations as small as possible.
|
||||||
|
annotations := make(map[string]string)
|
||||||
|
lastReloadedResourceName := fmt.Sprintf("%s/%s",
|
||||||
|
constants.ReloaderAnnotationPrefix,
|
||||||
|
constants.LastReloadedFromAnnotation,
|
||||||
|
)
|
||||||
|
|
||||||
|
lastReloadedResource, err := json.Marshal(target)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations[lastReloadedResourceName] = string(lastReloadedResource)
|
||||||
|
return annotations, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateContainerEnvVars(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) constants.Result {
|
||||||
var result constants.Result
|
var result constants.Result
|
||||||
envVar := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + config.Type
|
envVar := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + config.Type
|
||||||
container := getContainerToUpdate(upgradeFuncs, item, config, autoReload)
|
container := getContainerUsingResource(upgradeFuncs, item, config, autoReload)
|
||||||
|
|
||||||
if container == nil {
|
if container == nil {
|
||||||
return constants.NoContainerFound
|
return constants.NoContainerFound
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
|||||||
package options
|
package options
|
||||||
|
|
||||||
|
import "github.com/stakater/Reloader/internal/pkg/constants"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ConfigmapUpdateOnChangeAnnotation is an annotation to detect changes in
|
// ConfigmapUpdateOnChangeAnnotation is an annotation to detect changes in
|
||||||
// configmaps specified by name
|
// configmaps specified by name
|
||||||
@@ -17,6 +19,8 @@ var (
|
|||||||
SearchMatchAnnotation = "reloader.stakater.com/match"
|
SearchMatchAnnotation = "reloader.stakater.com/match"
|
||||||
// LogFormat is the log format to use (json, or empty string for default)
|
// LogFormat is the log format to use (json, or empty string for default)
|
||||||
LogFormat = ""
|
LogFormat = ""
|
||||||
// Adds support for argo rollouts
|
// IsArgoRollouts Adds support for argo rollouts
|
||||||
IsArgoRollouts = "false"
|
IsArgoRollouts = "false"
|
||||||
|
// ReloadStrategy Specify the update strategy
|
||||||
|
ReloadStrategy = constants.EnvVarsReloadStrategy
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package testutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -563,8 +565,8 @@ func GetSecretWithUpdatedLabel(namespace string, secretName string, label string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResourceSHA returns the SHA value of given environment variable
|
// GetResourceSHAFromEnvVar returns the SHA value of given environment variable
|
||||||
func GetResourceSHA(containers []v1.Container, envVar string) string {
|
func GetResourceSHAFromEnvVar(containers []v1.Container, envVar string) string {
|
||||||
for i := range containers {
|
for i := range containers {
|
||||||
envs := containers[i].Env
|
envs := containers[i].Env
|
||||||
for j := range envs {
|
for j := range envs {
|
||||||
@@ -576,6 +578,28 @@ func GetResourceSHA(containers []v1.Container, envVar string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetResourceSHAFromAnnotation returns the SHA value of given environment variable
|
||||||
|
func GetResourceSHAFromAnnotation(podAnnotations map[string]string) string {
|
||||||
|
lastReloadedResourceName := fmt.Sprintf("%s/%s",
|
||||||
|
constants.ReloaderAnnotationPrefix,
|
||||||
|
constants.LastReloadedFromAnnotation,
|
||||||
|
)
|
||||||
|
|
||||||
|
annotationJson, ok := podAnnotations[lastReloadedResourceName]
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var last util.ReloadSource
|
||||||
|
bytes := []byte(annotationJson)
|
||||||
|
err := json.Unmarshal(bytes, &last)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return last.Hash
|
||||||
|
}
|
||||||
|
|
||||||
//ConvertResourceToSHA generates SHA from secret or configmap data
|
//ConvertResourceToSHA generates SHA from secret or configmap data
|
||||||
func ConvertResourceToSHA(resourceType string, namespace string, resourceName string, data string) string {
|
func ConvertResourceToSHA(resourceType string, namespace string, resourceName string, data string) string {
|
||||||
values := []string{}
|
values := []string{}
|
||||||
@@ -806,8 +830,8 @@ func RandSeq(n int) string {
|
|||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyResourceUpdate verifies whether the rolling upgrade happened or not
|
// VerifyResourceEnvVarUpdate verifies whether the rolling upgrade happened or not
|
||||||
func VerifyResourceUpdate(clients kube.Clients, config util.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
func VerifyResourceEnvVarUpdate(clients kube.Clients, config util.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
||||||
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
|
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
|
||||||
for _, i := range items {
|
for _, i := range items {
|
||||||
containers := upgradeFuncs.ContainersFunc(i)
|
containers := upgradeFuncs.ContainersFunc(i)
|
||||||
@@ -836,7 +860,45 @@ func VerifyResourceUpdate(clients kube.Clients, config util.Config, envVarPostfi
|
|||||||
|
|
||||||
if matches {
|
if matches {
|
||||||
envName := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + envVarPostfix
|
envName := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + envVarPostfix
|
||||||
updated := GetResourceSHA(containers, envName)
|
updated := GetResourceSHAFromEnvVar(containers, envName)
|
||||||
|
if updated == config.SHAValue {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyResourceAnnotationUpdate verifies whether the rolling upgrade happened or not
|
||||||
|
func VerifyResourceAnnotationUpdate(clients kube.Clients, config util.Config, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
||||||
|
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
|
||||||
|
for _, i := range items {
|
||||||
|
podAnnotations := upgradeFuncs.PodAnnotationsFunc(i)
|
||||||
|
// match statefulsets with the correct annotation
|
||||||
|
annotationValue := util.ToObjectMeta(i).Annotations[config.Annotation]
|
||||||
|
searchAnnotationValue := util.ToObjectMeta(i).Annotations[options.AutoSearchAnnotation]
|
||||||
|
reloaderEnabledValue := util.ToObjectMeta(i).Annotations[options.ReloaderAutoAnnotation]
|
||||||
|
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
|
||||||
|
matches := false
|
||||||
|
if err == nil && reloaderEnabled {
|
||||||
|
matches = true
|
||||||
|
} else if annotationValue != "" {
|
||||||
|
values := strings.Split(annotationValue, ",")
|
||||||
|
for _, value := range values {
|
||||||
|
value = strings.Trim(value, " ")
|
||||||
|
if value == config.ResourceName {
|
||||||
|
matches = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if searchAnnotationValue == "true" {
|
||||||
|
if config.ResourceAnnotations[options.SearchMatchAnnotation] == "true" {
|
||||||
|
matches = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches {
|
||||||
|
updated := GetResourceSHAFromAnnotation(podAnnotations)
|
||||||
if updated == config.SHAValue {
|
if updated == config.SHAValue {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
39
internal/pkg/util/reload_source.go
Normal file
39
internal/pkg/util/reload_source.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type ReloadSource struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
ContainerRefs []string `json:"containerRefs"`
|
||||||
|
ObservedAt int64 `json:"observedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReloadSource(
|
||||||
|
resourceName string,
|
||||||
|
resourceNamespace string,
|
||||||
|
resourceType string,
|
||||||
|
resourceHash string,
|
||||||
|
containerRefs []string,
|
||||||
|
) ReloadSource {
|
||||||
|
return ReloadSource{
|
||||||
|
ObservedAt: time.Now().Unix(),
|
||||||
|
Name: resourceName,
|
||||||
|
Namespace: resourceNamespace,
|
||||||
|
Type: resourceType,
|
||||||
|
Hash: resourceHash,
|
||||||
|
ContainerRefs: containerRefs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReloadSourceFromConfig(config Config, containerRefs []string) ReloadSource {
|
||||||
|
return NewReloadSource(
|
||||||
|
config.ResourceName,
|
||||||
|
config.Namespace,
|
||||||
|
config.Type,
|
||||||
|
config.SHAValue,
|
||||||
|
containerRefs,
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user