Skip to content

Commit

Permalink
Ensure imagepullsecrets and hooks informer for dynamic namespaces eve…
Browse files Browse the repository at this point in the history
…n if API restarts
  • Loading branch information
sgalsaleh committed Sep 26, 2023
1 parent bc8004b commit 20348d5
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 115 deletions.
6 changes: 3 additions & 3 deletions pkg/apiserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ func Start(params *APIServerParams) {

if !util.IsHelmManaged() {
client := &client.Client{
TargetNamespace: util.AppNamespace(),
ExistingInformers: map[string]bool{},
HookStopChans: []chan struct{}{},
TargetNamespace: util.AppNamespace(),
ExistingHookInformers: map[string]bool{},
HookStopChans: []chan struct{}{},
}
store := store.GetStore()
k8sClientset, err := k8sutil.GetClientset()
Expand Down
86 changes: 49 additions & 37 deletions pkg/operator/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,18 @@ type Client struct {
watchedNamespaces []string
imagePullSecrets []string

appStateMonitor *appstate.Monitor
HookStopChans []chan struct{}
namespaceStopChan chan struct{}
ExistingInformers map[string]bool // namespaces map to invoke the Informer once during deploy
appStateMonitor *appstate.Monitor
HookStopChans []chan struct{}
namespaceStopChan chan struct{}
ExistingHookInformers map[string]bool // namespaces map to invoke the Informer once during deploy
}

func (c *Client) Init() error {
if _, ok := c.ExistingInformers[c.TargetNamespace]; !ok {
c.ExistingInformers[c.TargetNamespace] = true
if _, ok := c.ExistingHookInformers[c.TargetNamespace]; !ok {
c.ExistingHookInformers[c.TargetNamespace] = true
if err := c.runHooksInformer(c.TargetNamespace); err != nil {
// we don't fail here...
log.Printf("error registering cleanup hooks for TargetNamespace: %s: %s",
c.TargetNamespace, err.Error())
log.Printf("error registering cleanup hooks for TargetNamespace: %s: %s", c.TargetNamespace, err.Error())
}
}

Expand Down Expand Up @@ -125,6 +124,45 @@ func (c *Client) runAppStateMonitor() error {
return errors.New("app state monitor shutdown")
}

func (c *Client) RestartNamespacesInformer(namespaces []string, imagePullSecrets []string) {
for _, ns := range namespaces {
if ns == "*" {
continue
}
if err := c.ensureNamespacePresent(ns); err != nil {
// we don't fail here...
log.Printf("error creating namespace: %s", err.Error())
}
if err := c.ensureImagePullSecretsPresent(ns, imagePullSecrets); err != nil {
// we don't fail here...
log.Printf("error ensuring image pull secrets for namespace %s: %s", ns, err.Error())
}
}

c.imagePullSecrets = imagePullSecrets
c.watchedNamespaces = namespaces

c.shutdownNamespacesInformer()
if len(c.watchedNamespaces) > 0 {
c.runNamespacesInformer()
}
}

func (c *Client) ApplyHooksInformer(namespaces []string) {
for _, ns := range namespaces {
if ns == "*" {
continue
}
if _, ok := c.ExistingHookInformers[ns]; !ok {
c.ExistingHookInformers[ns] = true
if err := c.runHooksInformer(ns); err != nil {
// we don't fail here...
log.Printf("error registering cleanup hooks for namespace: %s: %s", ns, err.Error())
}
}
}
}

func (c *Client) DeployApp(deployArgs operatortypes.DeployAppArgs) (deployed bool, finalError error) {
log.Println("received a deploy request for", deployArgs.AppSlug)

Expand All @@ -142,6 +180,9 @@ func (c *Client) DeployApp(deployArgs operatortypes.DeployAppArgs) (deployed boo
}
}()

c.RestartNamespacesInformer(deployArgs.AdditionalNamespaces, deployArgs.ImagePullSecrets)
c.ApplyHooksInformer(deployArgs.AdditionalNamespaces)

deployRes, deployError = c.deployManifests(deployArgs)
if deployError != nil {
deployRes = &deployResult{}
Expand All @@ -160,11 +201,6 @@ func (c *Client) DeployApp(deployArgs operatortypes.DeployAppArgs) (deployed boo
return
}

c.shutdownNamespacesInformer()
if len(c.watchedNamespaces) > 0 {
c.runNamespacesInformer()
}

return
}

Expand Down Expand Up @@ -214,30 +250,6 @@ func (c *Client) deployManifests(deployArgs operatortypes.DeployAppArgs) (*deplo
}
}

for _, additionalNamespace := range deployArgs.AdditionalNamespaces {
if additionalNamespace == "*" {
continue
}
if err := c.ensureNamespacePresent(additionalNamespace); err != nil {
// we don't fail here...
log.Printf("error creating namespace: %s", err.Error())
}
if err := c.ensureImagePullSecretsPresent(additionalNamespace, deployArgs.ImagePullSecrets); err != nil {
// we don't fail here...
log.Printf("error ensuring image pull secrets for namespace %s: %s", additionalNamespace, err.Error())
}
if _, ok := c.ExistingInformers[additionalNamespace]; !ok {
c.ExistingInformers[additionalNamespace] = true
if err := c.runHooksInformer(additionalNamespace); err != nil {
// we don't fail here...
log.Printf("error registering cleanup hooks for additionalNamespace: %s: %s",
additionalNamespace, err.Error())
}
}
}
c.imagePullSecrets = deployArgs.ImagePullSecrets
c.watchedNamespaces = deployArgs.AdditionalNamespaces

result, err := c.ensureResourcesPresent(deployArgs)
if err != nil {
return nil, errors.Wrap(err, "failed to deploy")
Expand Down
2 changes: 2 additions & 0 deletions pkg/operator/client/client_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ type ClientInterface interface {
DeployApp(deployArgs operatortypes.DeployAppArgs) (deployed bool, finalError error)
UndeployApp(undeployArgs operatortypes.UndeployAppArgs) error
ApplyAppInformers(args operatortypes.AppInformersArgs)
RestartNamespacesInformer(namespaces []string, imagePullSecrets []string)
ApplyHooksInformer(namespaces []string)
}
4 changes: 4 additions & 0 deletions pkg/operator/client/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type deployResult struct {
}

func (c *Client) ensureNamespacePresent(name string) error {
logger.Infof("ensuring namespace %s", name)

clientset, err := k8sutil.GetClientset()
if err != nil {
return errors.Wrap(err, "failed to get clientset")
Expand Down Expand Up @@ -71,6 +73,8 @@ func (c *Client) ensureNamespacePresent(name string) error {
}

func (c *Client) ensureImagePullSecretsPresent(namespace string, imagePullSecrets []string) error {
logger.Infof("ensuring image pull secrets for namespace %s", namespace)

imagePullSecretsMtx.Lock()
defer imagePullSecretsMtx.Unlock()

Expand Down
2 changes: 2 additions & 0 deletions pkg/operator/client/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (

// runHooksInformer will create goroutines to start various informers for kots objects
func (c *Client) runHooksInformer(namespace string) error {
logger.Infof("running hooks informer for namespace %s", namespace)

clientset, err := k8sutil.GetClientset()
if err != nil {
return errors.Wrap(err, "failed to get clientset")
Expand Down
2 changes: 2 additions & 0 deletions pkg/operator/client/namespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func (c *Client) runNamespacesInformer() error {
// we don't fail here...
log.Printf("error ensuring image pull secrets for namespace %s: %s", addedNamespace.Name, err.Error())
}

c.ApplyHooksInformer([]string{addedNamespace.Name})
}
},
})
Expand Down
44 changes: 0 additions & 44 deletions pkg/operator/helm.go

This file was deleted.

72 changes: 72 additions & 0 deletions pkg/operator/image_pull_secrets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package operator

import (
"os"
"path/filepath"

"github.com/pkg/errors"
"github.com/replicatedhq/kots/pkg/util"
)

func getImagePullSecrets(deployedVersionArchive string) ([]string, error) {
imagePullSecrets := []string{}

secretFilename := filepath.Join(deployedVersionArchive, "overlays", "midstream", "secret.yaml")
_, err := os.Stat(secretFilename)
if err != nil && !os.IsNotExist(err) {
return nil, errors.Wrap(err, "failed to os stat image pull secret file")
}
if err == nil {
b, err := os.ReadFile(secretFilename)
if err != nil {
return nil, errors.Wrap(err, "failed to read image pull secret file")
}
secrets := util.ConvertToSingleDocs(b)
for _, secret := range secrets {
imagePullSecrets = append(imagePullSecrets, string(secret))
}
}

chartPullSecrets, err := getChartsImagePullSecrets(deployedVersionArchive)
if err != nil {
return nil, errors.Wrap(err, "failed to read image pull secret files from charts")
}
imagePullSecrets = append(imagePullSecrets, chartPullSecrets...)
imagePullSecrets = deduplicateSecrets(imagePullSecrets)

return imagePullSecrets, nil
}

func getChartsImagePullSecrets(deployedVersionArchive string) ([]string, error) {
archiveChartDir := filepath.Join(deployedVersionArchive, "overlays", "midstream", "charts")
chartDirs, err := os.ReadDir(archiveChartDir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, errors.Wrap(err, "failed to read charts directory")
}

imagePullSecrets := []string{}
for _, chartDir := range chartDirs {
if !chartDir.IsDir() {
continue
}

secretFilename := filepath.Join(archiveChartDir, chartDir.Name(), "secret.yaml")
secretData, err := os.ReadFile(secretFilename)
if err != nil {
if os.IsNotExist(err) {
continue
}
return nil, errors.Wrap(err, "failed to read helm tar.gz file")
}

secrets := util.ConvertToSingleDocs(secretData)
for _, secret := range secrets {
imagePullSecrets = append(imagePullSecrets, string(secret))
}
}

return imagePullSecrets, nil
}
Loading

0 comments on commit 20348d5

Please sign in to comment.