Skip to content

Commit

Permalink
All pull secrets added to OA,AG specs and used by ImageInstaller
Browse files Browse the repository at this point in the history
  • Loading branch information
aorcholski committed Jul 4, 2024
1 parent 32dbd89 commit b6c318d
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 58 deletions.
16 changes: 9 additions & 7 deletions pkg/api/v1beta2/dynakube/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,16 @@ func (dk *DynaKube) PullSecretName() string {
return dk.Name + PullSecretSuffix
}

// PullSecretWithoutData returns a secret which can be used to query the actual secrets data from the cluster.
func (dk *DynaKube) PullSecretWithoutData() corev1.Secret {
return corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: dk.PullSecretName(),
Namespace: dk.Namespace,
},
// PullSecretsNames returns the names of the pull secrets to be used for immutable images.
func (dk *DynaKube) PullSecretsNames() []string {
names := []string{
dk.Name + PullSecretSuffix,
}
if dk.Spec.CustomPullSecret != "" {
names = append(names, dk.Spec.CustomPullSecret)
}

return names
}

func (dk *DynaKube) NeedsReadOnlyOneAgents() bool {
Expand Down
3 changes: 0 additions & 3 deletions pkg/controllers/csi/provisioner/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer"
"github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/image"
"github.com/Dynatrace/dynatrace-operator/pkg/injection/codemodule/installer/url"
"github.com/Dynatrace/dynatrace-operator/pkg/oci/registry"
"github.com/Dynatrace/dynatrace-operator/pkg/util/dtotel"
"github.com/pkg/errors"
"github.com/spf13/afero"
Expand Down Expand Up @@ -61,7 +60,6 @@ type OneAgentProvisioner struct {
dynatraceClientBuilder dynatraceclient.Builder
urlInstallerBuilder urlInstallerBuilder
imageInstallerBuilder imageInstallerBuilder
registryClientBuilder registry.ClientBuilder
opts dtcsi.CSIOptions
path metadata.PathResolver
}
Expand All @@ -80,7 +78,6 @@ func NewOneAgentProvisioner(mgr manager.Manager, opts dtcsi.CSIOptions, db metad
dynatraceClientBuilder: dynatraceclient.NewBuilder(mgr.GetAPIReader()),
urlInstallerBuilder: url.NewUrlInstaller,
imageInstallerBuilder: image.NewImageInstaller,
registryClientBuilder: registry.NewClient,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ func (statefulSetBuilder Builder) addUserAnnotations(sts *appsv1.StatefulSet) {
}

func (statefulSetBuilder Builder) addTemplateSpec(sts *appsv1.StatefulSet) {
imagePullSecrets := make([]corev1.LocalObjectReference, 0)
for _, pullSecretName := range statefulSetBuilder.dynakube.PullSecretsNames() {
imagePullSecrets = append(imagePullSecrets, corev1.LocalObjectReference{
Name: pullSecretName,
})
}

podSpec := corev1.PodSpec{
Containers: statefulSetBuilder.buildBaseContainer(),
NodeSelector: statefulSetBuilder.capability.Properties().NodeSelector,
Expand All @@ -129,9 +136,7 @@ func (statefulSetBuilder Builder) addTemplateSpec(sts *appsv1.StatefulSet) {
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
ImagePullSecrets: []corev1.LocalObjectReference{
{Name: statefulSetBuilder.dynakube.PullSecretName()},
},
ImagePullSecrets: imagePullSecrets,
PriorityClassName: statefulSetBuilder.dynakube.Spec.ActiveGate.PriorityClassName,
DNSPolicy: statefulSetBuilder.dynakube.Spec.ActiveGate.DNSPolicy,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ func TestAddTemplateSpec(t *testing.T) {

assert.NotEmpty(t, spec.Containers)
assert.NotEmpty(t, spec.Affinity)
assert.Equal(t, dynakube.PullSecretName(), spec.ImagePullSecrets[0].Name)
assert.Equal(t, len(dynakube.PullSecretsNames()), len(spec.ImagePullSecrets))
assert.Equal(t, dynakube.PullSecretsNames()[0], spec.ImagePullSecrets[0].Name)
})

t.Run("adds capability specific stuff", func(t *testing.T) {
Expand Down
3 changes: 0 additions & 3 deletions pkg/controllers/dynakube/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/proxy"
"github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token"
"github.com/Dynatrace/dynatrace-operator/pkg/injection/namespace/mapper"
"github.com/Dynatrace/dynatrace-operator/pkg/oci/registry"
"github.com/Dynatrace/dynatrace-operator/pkg/util/hasher"
"github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/env"
"github.com/Dynatrace/dynatrace-operator/pkg/util/kubesystem"
Expand Down Expand Up @@ -69,7 +68,6 @@ func NewDynaKubeController(kubeClient client.Client, apiReader client.Reader, co
clusterID: clusterID,
dynatraceClientBuilder: dynatraceclient.NewBuilder(apiReader),
istioClientBuilder: istio.NewClient,
registryClientBuilder: registry.NewClient,

deploymentMetadataReconcilerBuilder: deploymentmetadata.NewReconciler,
activeGateReconcilerBuilder: activegate.NewReconciler,
Expand Down Expand Up @@ -102,7 +100,6 @@ type Controller struct {
dynatraceClientBuilder dynatraceclient.Builder
config *rest.Config
istioClientBuilder istio.ClientBuilder
registryClientBuilder registry.ClientBuilder

deploymentMetadataReconcilerBuilder deploymentmetadata.ReconcilerBuilder
activeGateReconcilerBuilder activegate.ReconcilerBuilder
Expand Down
1 change: 0 additions & 1 deletion pkg/controllers/dynakube/controller_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ func createFakeClientAndReconciler(t *testing.T, mockClient dtclient.Client, ins
controller := &Controller{
client: fakeClient,
apiReader: fakeClient,
registryClientBuilder: createFakeRegistryClientBuilder(t),
dynatraceClientBuilder: mockDtcBuilder,
fs: afero.Afero{Fs: afero.NewMemMapFs()},
deploymentMetadataReconcilerBuilder: deploymentmetadata.NewReconciler,
Expand Down
30 changes: 3 additions & 27 deletions pkg/controllers/dynakube/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,11 @@ import (
"github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/istio"
"github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/oneagent"
"github.com/Dynatrace/dynatrace-operator/pkg/controllers/dynakube/token"
"github.com/Dynatrace/dynatrace-operator/pkg/oci/registry"
dtwebhook "github.com/Dynatrace/dynatrace-operator/pkg/webhook"
dtclientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace"
controllermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers"
dtbuildermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers/dynakube/dynatraceclient"
injectionmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/controllers/dynakube/injection"
registrymock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/oci/registry"
containerv1 "github.com/google/go-containerregistry/pkg/v1"
fakecontainer "github.com/google/go-containerregistry/pkg/v1/fake"
"github.com/pkg/errors"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -343,10 +339,9 @@ func TestReconcileComponents(t *testing.T) {
mockInjectionReconciler.On("Reconcile", mock.Anything).Return(errors.New("BOOM"))

controller := &Controller{
client: fakeClient,
apiReader: fakeClient,
fs: afero.Afero{Fs: afero.NewMemMapFs()},
registryClientBuilder: createFakeRegistryClientBuilder(t),
client: fakeClient,
apiReader: fakeClient,
fs: afero.Afero{Fs: afero.NewMemMapFs()},

activeGateReconcilerBuilder: createActivegateReconcilerBuilder(mockActiveGateReconciler),
injectionReconcilerBuilder: createInjectionReconcilerBuilder(mockInjectionReconciler),
Expand Down Expand Up @@ -374,7 +369,6 @@ func TestReconcileComponents(t *testing.T) {
client: fakeClient,
apiReader: fakeClient,
fs: afero.Afero{Fs: afero.NewMemMapFs()},
registryClientBuilder: createFakeRegistryClientBuilder(t),
activeGateReconcilerBuilder: createActivegateReconcilerBuilder(mockActiveGateReconciler),
injectionReconcilerBuilder: createInjectionReconcilerBuilder(mockInjectionReconciler),
}
Expand Down Expand Up @@ -405,23 +399,6 @@ func createInjectionReconcilerBuilder(reconciler *injectionmock.Reconciler) inje
}
}

func createFakeRegistryClientBuilder(t *testing.T) func(options ...func(*registry.Client)) (registry.ImageGetter, error) {
fakeRegistryClient := registrymock.NewImageGetter(t)
fakeImage := &fakecontainer.FakeImage{}
fakeImage.ConfigFileStub = func() (*containerv1.ConfigFile, error) {
return &containerv1.ConfigFile{}, nil
}
_, _ = fakeImage.ConfigFile()
image := containerv1.Image(fakeImage)

fakeRegistryClient.On("GetImageVersion", mock.Anything, mock.Anything).Return(registry.ImageVersion{Version: "1.2.3.4-5"}, nil).Maybe()
fakeRegistryClient.On("PullImageInfo", mock.Anything, mock.Anything).Return(&image, nil).Maybe()

return func(options ...func(*registry.Client)) (registry.ImageGetter, error) {
return fakeRegistryClient, nil
}
}

type errorClient struct {
client.Client
}
Expand Down Expand Up @@ -537,7 +514,6 @@ func TestTokenConditions(t *testing.T) {
client: fakeClient,
apiReader: fakeClient,
dynatraceClientBuilder: mockDtcBuilder,
registryClientBuilder: createFakeRegistryClientBuilder(t),
}

_, err := controller.setupTokensAndClient(ctx, dynakube)
Expand Down
4 changes: 0 additions & 4 deletions pkg/controllers/dynakube/dtpullsecret/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ func NewReconciler(clt client.Client, apiReader client.Reader, dynakube *dynatra
}

func (r *Reconciler) Reconcile(ctx context.Context) error {
if r.dynakube.Spec.CustomPullSecret != "" {
return nil
}

if !(r.dynakube.NeedsOneAgent() || r.dynakube.NeedsActiveGate()) {
if meta.FindStatusCondition(*r.dynakube.Conditions(), PullSecretConditionType) == nil {
return nil // no condition == nothing is there to clean up
Expand Down
7 changes: 4 additions & 3 deletions pkg/controllers/dynakube/oneagent/daemonset/arguments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ const (
testKey = "test-key"
testValue = "test-value"

testClusterID = "test-cluster-id"
testURL = "https://testing.dev.dynatracelabs.com/api"
testName = "test-name"
testClusterID = "test-cluster-id"
testURL = "https://testing.dev.dynatracelabs.com/api"
testDynakubeName = "test-dynakube-name"
testName = "test-name"

testNewHostGroupName = "newhostgroup"
testOldHostGroupArgument = "--set-host-group=oldhostgroup"
Expand Down
9 changes: 8 additions & 1 deletion pkg/controllers/dynakube/oneagent/daemonset/daemonset.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,14 @@ func (b *builder) imagePullSecrets() []corev1.LocalObjectReference {
return []corev1.LocalObjectReference{}
}

return []corev1.LocalObjectReference{{Name: b.dk.PullSecretName()}}
imagePullSecrets := make([]corev1.LocalObjectReference, 0)
for _, pullSecretName := range b.dk.PullSecretsNames() {
imagePullSecrets = append(imagePullSecrets, corev1.LocalObjectReference{
Name: pullSecretName,
})
}

return imagePullSecrets
}

func (b *builder) securityContext() *corev1.SecurityContext {
Expand Down
8 changes: 6 additions & 2 deletions pkg/controllers/dynakube/oneagent/daemonset/daemonset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ func TestLabels(t *testing.T) {

func TestCustomPullSecret(t *testing.T) {
instance := dynakube.DynaKube{
ObjectMeta: metav1.ObjectMeta{
Name: testDynakubeName,
},
Spec: dynakube.DynaKubeSpec{
APIURL: testURL,
OneAgent: dynakube.OneAgentSpec{
Expand All @@ -144,8 +147,9 @@ func TestCustomPullSecret(t *testing.T) {

podSpecs := ds.Spec.Template.Spec
assert.NotNil(t, podSpecs)
assert.NotEmpty(t, podSpecs.ImagePullSecrets)
assert.Equal(t, testName, podSpecs.ImagePullSecrets[0].Name)
assert.Len(t, podSpecs.ImagePullSecrets, 2)
assert.Equal(t, testDynakubeName+dynakube.PullSecretSuffix, podSpecs.ImagePullSecrets[0].Name)
assert.Equal(t, testName, podSpecs.ImagePullSecrets[1].Name)
}

func TestResources(t *testing.T) {
Expand Down
3 changes: 1 addition & 2 deletions pkg/injection/codemodule/installer/image/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,14 @@ type Properties struct {
}

func NewImageInstaller(ctx context.Context, fs afero.Fs, props *Properties) (installer.Installer, error) {
pullSecret := props.Dynakube.PullSecretWithoutData()
defaultTransport := http.DefaultTransport.(*http.Transport).Clone()

transport, err := registry.PrepareTransportForDynaKube(ctx, props.ApiReader, defaultTransport, props.Dynakube)
if err != nil {
return nil, err
}

keychain, err := dockerkeychain.NewDockerKeychain(ctx, props.ApiReader, pullSecret)
keychain, err := dockerkeychain.NewDockerKeychains(ctx, props.ApiReader, props.Dynakube.Namespace, props.Dynakube.PullSecretsNames())
if err != nil {
return nil, err
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/injection/codemodule/installer/image/installer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ func TestNewImageInstaller(t *testing.T) {
},
Spec: dynatracev1beta2.DynaKubeSpec{},
}
pullSecret := dynakube.PullSecretWithoutData()
pullSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: dynakube.PullSecretName(),
Namespace: dynakube.Namespace,
},
}
pullSecret.Data = map[string][]byte{
corev1.DockerConfigJsonKey: []byte(emptyDockerConfig),
}
Expand Down
46 changes: 46 additions & 0 deletions pkg/oci/dockerkeychain/docker_keychain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/pkg/errors"
"golang.org/x/exp/maps"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Expand All @@ -20,6 +21,51 @@ type DockerKeychain struct {
mutex sync.Mutex
}

func NewDockerKeychains(ctx context.Context, apiReader client.Reader, namespaceName string, pullSecretsNames []string) (authn.Keychain, error) {
keychain := &DockerKeychain{}
err := keychain.loadDockerConfigFromSecrets(ctx, apiReader, namespaceName, pullSecretsNames)

return keychain, err
}

func (keychain *DockerKeychain) loadDockerConfigFromSecrets(ctx context.Context, apiReader client.Reader, namespaceName string, pullSecretsNames []string) error {
if len(pullSecretsNames) == 0 {
return nil
}

configFile := configfile.ConfigFile{
AuthConfigs: make(map[string]dockertypes.AuthConfig),
}

for _, pullSecretName := range pullSecretsNames {
pullSecret := corev1.Secret{}

if err := apiReader.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: pullSecretName}, &pullSecret); err != nil {
log.Info("failed to load registry pull secret", "name", pullSecretName, "namespace", namespaceName)

return errors.WithStack(err)
}

dockerAuths, err := extractDockerAuthsFromSecret(&pullSecret)
if err != nil {
log.Info("failed to parse pull secret content", "name", pullSecret.Name, "namespace", pullSecret.Namespace)

return err
}

err = configFile.LoadFromReader(bytes.NewReader(dockerAuths))
if err != nil {
return errors.WithStack(err)
}
}

keychain.dockerConfig = &configFile

log.Debug("loaded docker configs", "registries", maps.Keys(configFile.AuthConfigs))

return nil
}

func NewDockerKeychain(ctx context.Context, apiReader client.Reader, pullSecret corev1.Secret) (authn.Keychain, error) {
keychain := &DockerKeychain{}
err := keychain.loadDockerConfigFromSecret(ctx, apiReader, pullSecret)
Expand Down

0 comments on commit b6c318d

Please sign in to comment.