diff --git a/bundle/manifests/backstage-default-config_v1_configmap.yaml b/bundle/manifests/backstage-default-config_v1_configmap.yaml index 6a87fa42..69ef3253 100644 --- a/bundle/manifests/backstage-default-config_v1_configmap.yaml +++ b/bundle/manifests/backstage-default-config_v1_configmap.yaml @@ -159,11 +159,11 @@ data: replicas: 1 selector: matchLabels: - rhdh.redhat.com/app: # placeholder for 'backstage-' + rhdh.redhat.com/app: # placeholder for 'backstage-' template: metadata: labels: - rhdh.redhat.com/app: # placeholder for 'backstage-' + rhdh.redhat.com/app: # placeholder for 'backstage-' spec: automountServiceAccountToken: false # if securityContext not present in AKS/EKS, the error is like this: @@ -188,6 +188,9 @@ data: secretName: dynamic-plugins-npmrc - emptyDir: {} name: npmcacache + - name: audit-log-data + persistentVolumeClaim: + claimName: audit-log-pvc # placeholder for audit log pvc name initContainers: - name: install-dynamic-plugins command: @@ -203,7 +206,7 @@ data: type: RuntimeDefault capabilities: drop: - - ALL + - ALL env: - name: NPM_CONFIG_USERCONFIG value: /opt/app-root/src/.npmrc.dynamic-plugins @@ -270,6 +273,8 @@ data: volumeMounts: - mountPath: /opt/app-root/src/dynamic-plugins-root name: dynamic-plugins-root + - mountPath: /var/log/audit + name: audit-log-data resources: requests: cpu: 250m diff --git a/bundle/manifests/backstage-operator.clusterserviceversion.yaml b/bundle/manifests/backstage-operator.clusterserviceversion.yaml index 9578ec6d..691373d7 100644 --- a/bundle/manifests/backstage-operator.clusterserviceversion.yaml +++ b/bundle/manifests/backstage-operator.clusterserviceversion.yaml @@ -21,7 +21,7 @@ metadata: } ] capabilities: Seamless Upgrades - createdAt: "2024-07-16T20:47:15Z" + createdAt: "2024-07-25T15:35:46Z" operatorframework.io/suggested-namespace: backstage-system operators.operatorframework.io/builder: operator-sdk-v1.33.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 diff --git a/config/manager/default-config/audit-log-pvc.yaml b/config/manager/default-config/audit-log-pvc.yaml new file mode 100644 index 00000000..b8f0f6f8 --- /dev/null +++ b/config/manager/default-config/audit-log-pvc.yaml @@ -0,0 +1,11 @@ + +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: audit-log-pvc # will be replaced +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/config/manager/default-config/deployment.yaml b/config/manager/default-config/deployment.yaml index b9a9d471..a3bd44e4 100644 --- a/config/manager/default-config/deployment.yaml +++ b/config/manager/default-config/deployment.yaml @@ -6,11 +6,11 @@ spec: replicas: 1 selector: matchLabels: - rhdh.redhat.com/app: # placeholder for 'backstage-' + rhdh.redhat.com/app: # placeholder for 'backstage-' template: metadata: labels: - rhdh.redhat.com/app: # placeholder for 'backstage-' + rhdh.redhat.com/app: # placeholder for 'backstage-' spec: automountServiceAccountToken: false # if securityContext not present in AKS/EKS, the error is like this: @@ -35,6 +35,9 @@ spec: secretName: dynamic-plugins-npmrc - emptyDir: {} name: npmcacache + - name: audit-log-data + persistentVolumeClaim: + claimName: audit-log-pvc # placeholder for audit log pvc name initContainers: - name: install-dynamic-plugins command: @@ -50,7 +53,7 @@ spec: type: RuntimeDefault capabilities: drop: - - ALL + - ALL env: - name: NPM_CONFIG_USERCONFIG value: /opt/app-root/src/.npmrc.dynamic-plugins @@ -117,6 +120,8 @@ spec: volumeMounts: - mountPath: /opt/app-root/src/dynamic-plugins-root name: dynamic-plugins-root + - mountPath: /var/log/audit + name: audit-log-data resources: requests: cpu: 250m diff --git a/integration_tests/rhdh-config_test.go b/integration_tests/rhdh-config_test.go index 18175958..6c83e373 100644 --- a/integration_tests/rhdh-config_test.go +++ b/integration_tests/rhdh-config_test.go @@ -60,7 +60,7 @@ var _ = When("create default backstage", func() { g.Expect(initCont.VolumeMounts[1].MountPath).To(Equal("/opt/app-root/src/.npmrc.dynamic-plugins")) g.Expect(initCont.VolumeMounts[1].SubPath).To(Equal(".npmrc")) g.Expect(initCont.VolumeMounts[2].MountPath).To(Equal("/opt/app-root/src/.npm/_cacache")) - g.Expect(initCont.VolumeMounts[2].SubPath).To(BeEmpty()) + g.Expect(initCont.VolumeMounts[2].SubPath).To(BeEmpty()) g.Expect(initCont.VolumeMounts[3].MountPath).To(Equal("/opt/app-root/src/dynamic-plugins.yaml")) g.Expect(initCont.VolumeMounts[3].SubPath).To(Equal("dynamic-plugins.yaml")) g.Expect(initCont.VolumeMounts[3].Name). @@ -70,7 +70,7 @@ var _ = When("create default backstage", func() { g.Expect(initCont.Env[0].Name).To(Equal("NPM_CONFIG_USERCONFIG")) g.Expect(initCont.Env[0].Value).To(Equal("/opt/app-root/src/.npmrc.dynamic-plugins")) - g.Expect(deploy.Spec.Template.Spec.Volumes).To(HaveLen(5)) + g.Expect(deploy.Spec.Template.Spec.Volumes).To(HaveLen(6)) g.Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1)) mainCont := deploy.Spec.Template.Spec.Containers[0] g.Expect(mainCont.Args).To(HaveLen(4)) @@ -79,11 +79,13 @@ var _ = When("create default backstage", func() { g.Expect(mainCont.Args[2]).To(Equal("--config")) g.Expect(mainCont.Args[3]).To(Equal("/opt/app-root/src/default.app-config.yaml")) - g.Expect(mainCont.VolumeMounts).To(HaveLen(2)) + g.Expect(mainCont.VolumeMounts).To(HaveLen(3)) g.Expect(mainCont.VolumeMounts[0].MountPath).To(Equal("/opt/app-root/src/dynamic-plugins-root")) g.Expect(mainCont.VolumeMounts[0].SubPath).To(BeEmpty()) - g.Expect(mainCont.VolumeMounts[1].MountPath).To(Equal("/opt/app-root/src/default.app-config.yaml")) - g.Expect(mainCont.VolumeMounts[1].SubPath).To(Equal("default.app-config.yaml")) + g.Expect(mainCont.VolumeMounts[1].MountPath).To(Equal("/var/log/audit")) + g.Expect(mainCont.VolumeMounts[1].SubPath).To(BeEmpty()) + g.Expect(mainCont.VolumeMounts[2].MountPath).To(Equal("/opt/app-root/src/default.app-config.yaml")) + g.Expect(mainCont.VolumeMounts[2].SubPath).To(Equal("default.app-config.yaml")) }, 10*time.Second, time.Second).Should(Succeed()) diff --git a/pkg/model/audit-log-pvc.go b/pkg/model/audit-log-pvc.go new file mode 100644 index 00000000..3adfe9bb --- /dev/null +++ b/pkg/model/audit-log-pvc.go @@ -0,0 +1,81 @@ +// +// Copyright (c) 2023 Red Hat, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" + "redhat-developer/red-hat-developer-hub-operator/pkg/utils" + + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type AuditLogPvcFactory struct{} + +func (f AuditLogPvcFactory) newBackstageObject() RuntimeObject { + return &AuditLogPvc{} +} + +type AuditLogPvc struct { + pvc *corev1.PersistentVolumeClaim +} + +func init() { + registerConfig("audit-log-pvc.yaml", AuditLogPvcFactory{}) +} + +func AuditLogPvcDefaultName(backstageName string) string { + return utils.GenerateRuntimeObjectName(backstageName, "audit-log") +} + +// implementation of RuntimeObject interface +func (b *AuditLogPvc) Object() client.Object { + return b.pvc +} + +// implementation of RuntimeObject interface +func (b *AuditLogPvc) setObject(obj client.Object) { + b.pvc = nil + if obj != nil { + b.pvc = obj.(*corev1.PersistentVolumeClaim) + } +} + +// implementation of RuntimeObject interface +func (b *AuditLogPvc) addToModel(model *BackstageModel, backstage bsv1.Backstage) (bool, error) { + + if b.pvc != nil && model.localDbEnabled { + model.setRuntimeObject(b) + model.localAuditLogPvc = b + return true, nil + } + + return false, nil +} + +// implementation of RuntimeObject interface +func (b *AuditLogPvc) EmptyObject() client.Object { + return &corev1.PersistentVolumeClaim{} +} + +// implementation of RuntimeObject interface +func (b *AuditLogPvc) validate(model *BackstageModel, backstage bsv1.Backstage) error { + + return nil +} + +func (b *AuditLogPvc) setMetaInfo(backstageName string) { + b.pvc.SetName(AuditLogPvcDefaultName(backstageName)) +} diff --git a/pkg/model/deployment.go b/pkg/model/deployment.go index 607c425c..86062b2e 100644 --- a/pkg/model/deployment.go +++ b/pkg/model/deployment.go @@ -159,6 +159,7 @@ func (b *BackstageDeployment) setDeployment(backstage bsv1.Backstage) error { utils.SetImagePullSecrets(b.podSpec(), backstage.Spec.Application.ImagePullSecrets) b.setImage(backstage.Spec.Application.Image) b.addExtraEnvs(backstage.Spec.Application.ExtraEnvs) + b.setAuditLogClaimName(backstage) } // set from backstage.Spec.Deployment @@ -225,3 +226,12 @@ func (b *BackstageDeployment) addExtraEnvs(extraEnvs *bsv1.ExtraEnvs) { } } } + +func (b *BackstageDeployment) setAuditLogClaimName(backstage bsv1.Backstage) { + for k, v := range b.deployment.Spec.Template.Spec.Volumes { + + if v.Name == "audit-log-data" { + b.deployment.Spec.Template.Spec.Volumes[k].PersistentVolumeClaim.ClaimName = fmt.Sprintf("%s-audit-log", backstage.Name) + } + } +} diff --git a/pkg/model/deployment_test.go b/pkg/model/deployment_test.go index f257cbaa..14630936 100644 --- a/pkg/model/deployment_test.go +++ b/pkg/model/deployment_test.go @@ -16,17 +16,15 @@ package model import ( "context" + "fmt" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "testing" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - - "k8s.io/utils/ptr" - - bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" + "github.com/stretchr/testify/assert" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/stretchr/testify/assert" + "k8s.io/utils/ptr" ) var deploymentTestBackstage = bsv1.Backstage{ @@ -161,12 +159,12 @@ spec: // volumes // dynamic-plugins-root, dynamic-plugins-npmrc, my-vol - assert.Equal(t, 3, len(model.backstageDeployment.deployment.Spec.Template.Spec.Volumes)) + assert.Equal(t, 4, len(model.backstageDeployment.deployment.Spec.Template.Spec.Volumes)) assert.Equal(t, "dynamic-plugins-root", model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[0].Name) // overrides StorageClassName assert.Equal(t, "special", *model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[0].Ephemeral.VolumeClaimTemplate.Spec.StorageClassName) // adds new volume - assert.Equal(t, "my-vol", model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[2].Name) + assert.Equal(t, "my-vol", model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[3].Name) } // to remove when stop supporting v1alpha1 @@ -197,3 +195,21 @@ spec: assert.Equal(t, "deployment-image", model.backstageDeployment.container().Image) assert.Equal(t, int32(3), *model.backstageDeployment.deployment.Spec.Replicas) } + +func TestSetAuditLogClaimName(t *testing.T) { + bs := *deploymentTestBackstage.DeepCopy() + bs.Spec.Deployment = &bsv1.BackstageDeployment{} + testObj := createBackstageTest(bs).withDefaultConfig(true). + addToDefaultConfig("deployment.yaml", "janus-deployment.yaml") + + model, err := InitObjects(context.TODO(), bs, testObj.externalConfig, true, true, testObj.scheme) + assert.NoError(t, err) + + for _, v := range model.backstageDeployment.podSpec().Volumes { + if v.Name == "audit-log-data" { + if v.PersistentVolumeClaim.ClaimName != fmt.Sprintf("%s-audit-log", bs.Name) { + t.Errorf("wanted %s, got %s", fmt.Sprintf("%s-audit-log", bs.Name), v.PersistentVolumeClaim.ClaimName) + } + } + } +} diff --git a/pkg/model/dynamic-plugins_test.go b/pkg/model/dynamic-plugins_test.go index 7c4f7351..5592a481 100644 --- a/pkg/model/dynamic-plugins_test.go +++ b/pkg/model/dynamic-plugins_test.go @@ -93,7 +93,7 @@ func TestDefaultDynamicPlugins(t *testing.T) { //dynamic-plugins-root //dynamic-plugins-npmrc //vol-default-dynamic-plugins - assert.Equal(t, 3, len(model.backstageDeployment.deployment.Spec.Template.Spec.Volumes)) + assert.Equal(t, 4, len(model.backstageDeployment.deployment.Spec.Template.Spec.Volumes)) ic := initContainer(model) assert.NotNil(t, ic) diff --git a/pkg/model/runtime.go b/pkg/model/runtime.go index cdf26b49..8b910be3 100644 --- a/pkg/model/runtime.go +++ b/pkg/model/runtime.go @@ -52,6 +52,8 @@ type BackstageModel struct { LocalDbService *DbService LocalDbSecret *DbSecret + localAuditLogPvc *AuditLogPvc + route *BackstageRoute RuntimeObjects []RuntimeObject diff --git a/pkg/model/testdata/janus-deployment.yaml b/pkg/model/testdata/janus-deployment.yaml index d347a8e3..68df9c43 100644 --- a/pkg/model/testdata/janus-deployment.yaml +++ b/pkg/model/testdata/janus-deployment.yaml @@ -28,6 +28,9 @@ spec: defaultMode: 420 optional: true secretName: dynamic-plugins-npmrc + - name: audit-log-data + persistentVolumeClaim: + claimName: fooClaim initContainers: - command: - ./install-dynamic-plugins.sh @@ -83,6 +86,3 @@ spec: volumeMounts: - mountPath: /opt/app-root/src/dynamic-plugins-root name: dynamic-plugins-root - - -