From 3c4d5b609d07268d152d8504dffacad936c2c597 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 27 Dec 2023 15:11:12 +0100 Subject: [PATCH] Custom internal alias (#571) * Updated refs * Added DNSAliases to Application model. Removed admission controller, which was not in actual use.Removed use of NewApplication * Corrected DNS zone argument * DNSAlias renamed * Moved in method from radix-operator. Merge * Moved in method from radix-operator. Merge * Corrected dns alias property name * Get DNS alias using useraccount to list * Updated refs, fixed unit-tests * Merging * Fixed linter reported issues * Fixed unit-tests --- .gitignore | 1 + .../admission_controller.go | 93 ------------- .../admission_ra_handler.go | 48 ------- .../admission_ra_handler_test.go | 103 -------------- .../admission_rr_handler.go | 48 ------- .../admission_rr_handler_test.go | 103 -------------- .../testdata/radixconfig.yaml | 36 ----- .../testdata/sampleregistration.yaml | 14 -- .../applications_controller_test.go | 106 +++++++-------- api/applications/applications_handler.go | 22 +-- .../applications_handler_config.go | 2 + api/applications/models/application.go | 5 + api/applications/models/dns_alias.go | 32 +++++ api/buildsecrets/buildsecrets_test.go | 10 +- .../build_status_controller_test.go | 15 +-- api/defaults/environment_variables.go | 6 + api/deployments/component_controller_test.go | 30 ++--- api/deployments/component_handler.go | 4 +- api/deployments/deployment_controller_test.go | 25 ++-- api/deployments/models/component_builder.go | 8 +- api/deployments/models/deployment_builder.go | 4 +- .../environment_controller_secrets_test.go | 4 +- .../environment_controller_test.go | 93 ++++++------- api/environments/environment_handler.go | 9 +- .../env_vars_controller_test.go | 19 +-- .../env_vars_handler_test.go | 6 +- api/kubequery/radixdnsalias.go | 19 +++ api/kubequery/radixdnsalias_test.go | 24 ++++ api/models/application.go | 25 ++-- api/models/component.go | 4 +- api/models/dns_alias.go | 33 +++++ api/models/secret.go | 19 +-- api/privateimagehubs/internal/secrets.go | 59 ++++++++ .../privateimagehubs_controller.go | 2 +- .../privateimagehubs_handler.go | 16 +-- .../privateimagehubs_handler_test.go | 127 ++++++++++++++++++ api/router/server.go | 10 +- api/secrets/secret_controller_test.go | 47 +++---- api/utils/logs/logs.go | 4 +- api/utils/radixapplication.go | 38 +++++- api/utils/test.go | 24 ++-- go.mod | 11 +- go.sum | 20 +-- main.go | 15 +-- swaggerui/html/swagger.json | 56 ++++++++ 45 files changed, 673 insertions(+), 726 deletions(-) delete mode 100644 api/admissioncontrollers/admission_controller.go delete mode 100644 api/admissioncontrollers/admission_ra_handler.go delete mode 100644 api/admissioncontrollers/admission_ra_handler_test.go delete mode 100644 api/admissioncontrollers/admission_rr_handler.go delete mode 100644 api/admissioncontrollers/admission_rr_handler_test.go delete mode 100644 api/admissioncontrollers/testdata/radixconfig.yaml delete mode 100644 api/admissioncontrollers/testdata/sampleregistration.yaml create mode 100644 api/applications/models/dns_alias.go create mode 100644 api/defaults/environment_variables.go create mode 100644 api/kubequery/radixdnsalias.go create mode 100644 api/kubequery/radixdnsalias_test.go create mode 100644 api/models/dns_alias.go create mode 100644 api/privateimagehubs/internal/secrets.go create mode 100644 api/privateimagehubs/privateimagehubs_handler_test.go diff --git a/.gitignore b/.gitignore index ac1d952c..9846d745 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ Dockerfile.dev # binary created by goland with default settings main +swaggerui/statik.go diff --git a/api/admissioncontrollers/admission_controller.go b/api/admissioncontrollers/admission_controller.go deleted file mode 100644 index e67911b0..00000000 --- a/api/admissioncontrollers/admission_controller.go +++ /dev/null @@ -1,93 +0,0 @@ -package admissioncontrollers - -import ( - "encoding/json" - "net/http" - - "github.com/equinor/radix-api/models" - radixhttp "github.com/equinor/radix-common/net/http" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - log "github.com/sirupsen/logrus" - "k8s.io/api/admission/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes" -) - -const rootPath = "/admissioncontrollers" - -type admissionController struct { -} - -// NewAdmissionController Constructor -func NewAdmissionController() models.Controller { - return &admissionController{} -} - -// GetRoutes List the supported routes of this handler -func (ac *admissionController) GetRoutes() models.Routes { - routes := models.Routes{ - models.Route{ - Path: rootPath + "/registrations", - Method: "POST", - HandlerFunc: func(accounts models.Accounts, w http.ResponseWriter, r *http.Request) { - serve(accounts.ServiceAccount.Client, accounts.ServiceAccount.RadixClient, w, r, ValidateRegistrationChange) - }, - }, - models.Route{ - Path: rootPath + "/applications", - Method: "POST", - HandlerFunc: func(accounts models.Accounts, w http.ResponseWriter, r *http.Request) { - serve(accounts.ServiceAccount.Client, accounts.ServiceAccount.RadixClient, w, r, ValidateRadixConfigurationChange) - }, - }, - } - - return routes -} - -type admitFunc func(client kubernetes.Interface, radixclient radixclient.Interface, ar v1beta1.AdmissionReview) (bool, error) - -func serve(client kubernetes.Interface, radixclient radixclient.Interface, w http.ResponseWriter, r *http.Request, admit admitFunc) { - // verify the content type is accurate - contentType := r.Header.Get("Content-Type") - if contentType != "application/json" { - log.Errorf("contentType=%s, expect application/json", contentType) - return - } - - var reviewResponse *v1beta1.AdmissionResponse - ar := v1beta1.AdmissionReview{} - if err := json.NewDecoder(r.Body).Decode(&ar); err != nil { - reviewResponse = toAdmissionResponse(err) - } else { - isValid, err := admit(client, radixclient, ar) - if isValid { - reviewResponse = &v1beta1.AdmissionResponse{ - Allowed: true, - } - } else { - reviewResponse = toAdmissionResponse(err) - } - } - - response := v1beta1.AdmissionReview{} - if reviewResponse != nil { - response.Response = reviewResponse - response.Response.UID = ar.Request.UID - } - // reset the Object and OldObject, they are not needed in a response. - ar.Request.Object = runtime.RawExtension{} - ar.Request.OldObject = runtime.RawExtension{} - - radixhttp.JSONResponse(w, r, response) -} - -func toAdmissionResponse(err error) *v1beta1.AdmissionResponse { - return &v1beta1.AdmissionResponse{ - Allowed: false, - Result: &metav1.Status{ - Message: err.Error(), - }, - } -} diff --git a/api/admissioncontrollers/admission_ra_handler.go b/api/admissioncontrollers/admission_ra_handler.go deleted file mode 100644 index 676c7ccb..00000000 --- a/api/admissioncontrollers/admission_ra_handler.go +++ /dev/null @@ -1,48 +0,0 @@ -package admissioncontrollers - -import ( - "bytes" - "encoding/json" - "fmt" - - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/radixvalidators" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - log "github.com/sirupsen/logrus" - "k8s.io/api/admission/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -// ValidateRadixConfigurationChange Validates the radix configuration -func ValidateRadixConfigurationChange(client kubernetes.Interface, radixclient radixclient.Interface, ar v1beta1.AdmissionReview) (bool, error) { - log.Infof("admitting radix application configuration") - - radixApplication, err := decodeRadixConfiguration(ar) - if err != nil { - log.Warnf("radix app decoding failed") - return false, err - } - log.Infof("radix application decoded") - - isValid, err := radixvalidators.CanRadixApplicationBeInserted(radixclient, radixApplication) - if isValid { - log.Infof("radix app %s was admitted", radixApplication.Name) - } else { - log.Warnf("radix app %s was rejected", radixApplication.Name) - } - return isValid, err -} - -func decodeRadixConfiguration(ar v1beta1.AdmissionReview) (*v1.RadixApplication, error) { - rrResource := metav1.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixapplications"} - if ar.Request.Resource != rrResource { - return nil, fmt.Errorf("resource was %s, expect resource to be %s", ar.Request.Resource, rrResource) - } - - radixApplication := v1.RadixApplication{} - if err := json.NewDecoder(bytes.NewReader(ar.Request.Object.Raw)).Decode(&radixApplication); err != nil { - return nil, err - } - return &radixApplication, nil -} diff --git a/api/admissioncontrollers/admission_ra_handler_test.go b/api/admissioncontrollers/admission_ra_handler_test.go deleted file mode 100644 index dacbc9eb..00000000 --- a/api/admissioncontrollers/admission_ra_handler_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package admissioncontrollers_test - -import ( - "encoding/json" - "testing" - - . "github.com/equinor/radix-api/api/admissioncontrollers" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "k8s.io/api/admission/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes" - kubefake "k8s.io/client-go/kubernetes/fake" -) - -func Test_valid_ra_returns_true(t *testing.T) { - kubeclient, client, validRA := validRASetup() - admissionReview := admissionReviewMockApp(validRA) - isValid, err := ValidateRadixConfigurationChange(kubeclient, client, admissionReview) - - assert.True(t, isValid) - assert.Nil(t, err) -} - -func Test_invalid_ra_admission_review(t *testing.T) { - kubeclient, client, validRA := validRASetup() - t.Run("invalid resource type", func(t *testing.T) { - admissionReview := admissionReviewMockApp(validRA) - admissionReview.Request.Resource = metav1.GroupVersionResource{ - Group: "", - Version: "v1", - Resource: "namespaces", - } - isValid, err := ValidateRadixConfigurationChange(kubeclient, client, admissionReview) - - assert.False(t, isValid) - assert.NotNil(t, err) - }) - - t.Run("invalid encoded ra", func(t *testing.T) { - admissionReview := admissionReviewMockApp(validRA) - admissionReview.Request.Object = runtime.RawExtension{Raw: []byte("some invalid encoded rr")} - isValid, err := ValidateRadixConfigurationChange(kubeclient, client, admissionReview) - - assert.False(t, isValid) - assert.NotNil(t, err) - }) - - t.Run("invalid ra", func(t *testing.T) { - validRA.Name = "∞§|[][|§∞€INVALID_NAME" - admissionReview := admissionReviewMockApp(validRA) - isValid, err := ValidateRadixConfigurationChange(kubeclient, client, admissionReview) - - assert.False(t, isValid) - assert.NotNil(t, err) - }) -} - -func validRASetup() (kubernetes.Interface, radixclient.Interface, *v1.RadixApplication) { - validRA, _ := utils.GetRadixApplicationFromFile("testdata/radixconfig.yaml") - validRR, _ := utils.GetRadixRegistrationFromFile("testdata/sampleregistration.yaml") - kubeclient := kubefake.NewSimpleClientset() - client := radixfake.NewSimpleClientset(validRR) - - return kubeclient, client, validRA -} - -func admissionReviewMockApp(app *v1.RadixApplication) v1beta1.AdmissionReview { - obj := encodeRadixApplication(app) - return v1beta1.AdmissionReview{ - TypeMeta: metav1.TypeMeta{ - Kind: "AdmissionReview", - }, - Request: &v1beta1.AdmissionRequest{ - UID: "e911857d-c318-11e8-bbad-025000000001", - Kind: metav1.GroupVersionKind{ - Kind: "Namespace", - }, - Operation: "CREATE", - Resource: metav1.GroupVersionResource{ - Group: "radix.equinor.com", - Version: "v1", - Resource: "radixapplications", - }, - Object: runtime.RawExtension{ - Raw: obj, - }, - }, - } -} - -func encodeRadixApplication(app *v1.RadixApplication) []byte { - ret, err := json.Marshal(app) - if err != nil { - logrus.Errorln(err) - } - return ret -} diff --git a/api/admissioncontrollers/admission_rr_handler.go b/api/admissioncontrollers/admission_rr_handler.go deleted file mode 100644 index 3c3d5647..00000000 --- a/api/admissioncontrollers/admission_rr_handler.go +++ /dev/null @@ -1,48 +0,0 @@ -package admissioncontrollers - -import ( - "bytes" - "encoding/json" - "fmt" - - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/radixvalidators" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - log "github.com/sirupsen/logrus" - "k8s.io/api/admission/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -// ValidateRegistrationChange validates new app registration -func ValidateRegistrationChange(client kubernetes.Interface, radixclient radixclient.Interface, ar v1beta1.AdmissionReview) (bool, error) { - log.Infof("admitting radix registrations") - - radixRegistration, err := decodeRadixRegistration(ar) - if err != nil { - log.Warnf("radix reg decoding failed") - return false, err - } - log.Infof("radix registration decoded") - - err = radixvalidators.CanRadixRegistrationBeUpdated(radixRegistration) - if err != nil { - log.Warnf("radix reg %s was rejected", radixRegistration.Name) - return false, err - } - log.Infof("radix reg %s was admitted", radixRegistration.Name) - return true, nil -} - -func decodeRadixRegistration(ar v1beta1.AdmissionReview) (*v1.RadixRegistration, error) { - rrResource := metav1.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixregistrations"} - if ar.Request.Resource != rrResource { - return nil, fmt.Errorf("resource was %s, expect resource to be %s", ar.Request.Resource, rrResource) - } - - radixRegistration := v1.RadixRegistration{} - if err := json.NewDecoder(bytes.NewReader(ar.Request.Object.Raw)).Decode(&radixRegistration); err != nil { - return nil, err - } - return &radixRegistration, nil -} diff --git a/api/admissioncontrollers/admission_rr_handler_test.go b/api/admissioncontrollers/admission_rr_handler_test.go deleted file mode 100644 index acc01573..00000000 --- a/api/admissioncontrollers/admission_rr_handler_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package admissioncontrollers_test - -import ( - "encoding/json" - "testing" - - kubefake "k8s.io/client-go/kubernetes/fake" - - "github.com/sirupsen/logrus" - . "github.com/equinor/radix-api/api/admissioncontrollers" - "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" - "github.com/stretchr/testify/assert" - "k8s.io/api/admission/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes" -) - -func Test_valid_rr_returns_true(t *testing.T) { - kubeclient, client, validRR := validRRSetup() - admissionReview := admissionReviewMock(validRR) - isValid, err := ValidateRegistrationChange(kubeclient, client, admissionReview) - - assert.True(t, isValid) - assert.Nil(t, err) -} - -func Test_invalid_rr_admission_review(t *testing.T) { - kubeclient, client, validRR := validRRSetup() - t.Run("invalid resource type", func(t *testing.T) { - admissionReview := admissionReviewMock(validRR) - admissionReview.Request.Resource = metav1.GroupVersionResource{ - Group: "", - Version: "v1", - Resource: "namespaces", - } - isValid, err := ValidateRegistrationChange(kubeclient, client, admissionReview) - - assert.False(t, isValid) - assert.NotNil(t, err) - }) - - t.Run("invalid encoded rr", func(t *testing.T) { - admissionReview := admissionReviewMock(validRR) - admissionReview.Request.Object = runtime.RawExtension{Raw: []byte("some invalid encoded rr")} - isValid, err := ValidateRegistrationChange(kubeclient, client, admissionReview) - - assert.False(t, isValid) - assert.NotNil(t, err) - }) - - t.Run("invalid rr", func(t *testing.T) { - validRR.Name = "|[[]§∞§|INVALID_CHARACTERS" - admissionReview := admissionReviewMock(validRR) - isValid, err := ValidateRegistrationChange(kubeclient, client, admissionReview) - - assert.False(t, isValid) - assert.NotNil(t, err) - }) -} - -func validRRSetup() (kubernetes.Interface, radixclient.Interface, *v1.RadixRegistration) { - validRR, _ := utils.GetRadixRegistrationFromFile("testdata/sampleregistration.yaml") - kubeclient := kubefake.NewSimpleClientset() - client := radixfake.NewSimpleClientset() - - return kubeclient, client, validRR -} - -func admissionReviewMock(reg *v1.RadixRegistration) v1beta1.AdmissionReview { - obj := encodeRadixRegistration(reg) - return v1beta1.AdmissionReview{ - TypeMeta: metav1.TypeMeta{ - Kind: "AdmissionReview", - }, - Request: &v1beta1.AdmissionRequest{ - UID: "e911857d-c318-11e8-bbad-025000000001", - Kind: metav1.GroupVersionKind{ - Kind: "Namespace", - }, - Operation: "CREATE", - Resource: metav1.GroupVersionResource{ - Group: "radix.equinor.com", - Version: "v1", - Resource: "radixregistrations", - }, - Object: runtime.RawExtension{ - Raw: obj, - }, - }, - } -} - -func encodeRadixRegistration(reg *v1.RadixRegistration) []byte { - ret, err := json.Marshal(reg) - if err != nil { - logrus.Errorln(err) - } - return ret -} diff --git a/api/admissioncontrollers/testdata/radixconfig.yaml b/api/admissioncontrollers/testdata/radixconfig.yaml deleted file mode 100644 index 1d7360bc..00000000 --- a/api/admissioncontrollers/testdata/radixconfig.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: radix.equinor.com/v1 -kind: RadixApplication -metadata: - name: testapp -spec: - environments: - - name: dev - - name: prod - components: - - name: app - src: . - ports: - - name: http - port: 8080 - public: true - replicas: 4 - - name: redis - src: redis/ - ports: - - name: http - port: 6379 - public: false - environmentVariables: - - environment: dev - variables: - DB_HOST: "useless-dev" - DB_PORT: "1234" - - environment: prod - variables: - DB_HOST: "useless-prod" - DB_PORT: "9876" - secrets: - - db-pass - - db-pass2 - - db-pass3 - \ No newline at end of file diff --git a/api/admissioncontrollers/testdata/sampleregistration.yaml b/api/admissioncontrollers/testdata/sampleregistration.yaml deleted file mode 100644 index 94c18176..00000000 --- a/api/admissioncontrollers/testdata/sampleregistration.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: radix.equinor.com/v1 -kind: RadixRegistration -metadata: - name: testapp -spec: - cloneURL: "git@github.com:equinor/testapp.git" - sharedSecret: "NotSoSecret" - adGroups: - - "a6a3b81b-34gd-sfsf-saf2-7986371ea35f" - secrets: - test: test - creator: "not-existing-test-radix-email@equinor.com" - configBranch: "main" - configurationItem: "2b0781a7db131784551ea1ea4b9619c9" diff --git a/api/applications/applications_controller_test.go b/api/applications/applications_controller_test.go index 64ffd996..085422a6 100644 --- a/api/applications/applications_controller_test.go +++ b/api/applications/applications_controller_test.go @@ -45,14 +45,13 @@ import ( const ( clusterName = "AnyClusterName" - dnsZone = "dev.radix.equinor.com" appAliasDNSZone = "app.dev.radix.equinor.com" egressIps = "0.0.0.0" subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" ) -func setupTest(requireAppConfigurationItem, requireAppADGroups bool) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, prometheusclient.Interface, secretsstorevclient.Interface) { - return setupTestWithFactory(newTestApplicationHandlerFactory( +func setupTest(t *testing.T, requireAppConfigurationItem, requireAppADGroups bool) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, prometheusclient.Interface, secretsstorevclient.Interface) { + return setupTestWithFactory(t, newTestApplicationHandlerFactory( ApplicationHandlerConfig{RequireAppConfigurationItem: requireAppConfigurationItem, RequireAppADGroups: requireAppADGroups}, func(ctx context.Context, kubeClient kubernetes.Interface, namespace string, configMapName string) (bool, error) { return true, nil @@ -60,7 +59,7 @@ func setupTest(requireAppConfigurationItem, requireAppADGroups bool) (*commontes )) } -func setupTestWithFactory(handlerFactory ApplicationHandlerFactory) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, prometheusclient.Interface, secretsstorevclient.Interface) { +func setupTestWithFactory(t *testing.T, handlerFactory ApplicationHandlerFactory) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, prometheusclient.Interface, secretsstorevclient.Interface) { // Setup kubeclient := kubefake.NewSimpleClientset() radixclient := fake.NewSimpleClientset() @@ -69,7 +68,8 @@ func setupTestWithFactory(handlerFactory ApplicationHandlerFactory) (*commontest // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) _ = os.Setenv(defaults.ActiveClusternameEnvironmentVariable, clusterName) // controllerTestUtils is used for issuing HTTP request and processing responses @@ -89,7 +89,7 @@ func setupTestWithFactory(handlerFactory ApplicationHandlerFactory) (*commontest } func TestGetApplications_HasAccessToSomeRR(t *testing.T) { - commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient := setupTest(true, true) + commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient := setupTest(t, true, true) _, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration(). WithCloneURL("git@github.com:Equinor/my-app.git")) @@ -156,7 +156,7 @@ func TestGetApplications_HasAccessToSomeRR(t *testing.T) { func TestGetApplications_WithFilterOnSSHRepo_Filter(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) _, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration(). WithCloneURL("git@github.com:Equinor/my-app.git")) require.NoError(t, err) @@ -195,7 +195,7 @@ func TestGetApplications_WithFilterOnSSHRepo_Filter(t *testing.T) { func TestSearchApplicationsPost(t *testing.T) { // Setup - commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient := setupTest(true, true) + commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient := setupTest(t, true, true) appNames := []string{"app-1", "app-2"} for _, appName := range appNames { @@ -319,7 +319,7 @@ func TestSearchApplicationsPost(t *testing.T) { func TestSearchApplicationsPost_WithJobs_ShouldOnlyHaveLatest(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t, true, true) apps := []applicationModels.Application{ {Name: "app-1", Jobs: []*jobModels.JobSummary{ {Name: "app-1-job-1", Started: "2018-11-12T11:45:26Z"}, @@ -372,7 +372,7 @@ func TestSearchApplicationsPost_WithJobs_ShouldOnlyHaveLatest(t *testing.T) { func TestSearchApplicationsGet(t *testing.T) { // Setup - commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient := setupTest(true, true) + commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient := setupTest(t, true, true) appNames := []string{"app-1", "app-2"} for _, appName := range appNames { @@ -486,7 +486,7 @@ func TestSearchApplicationsGet(t *testing.T) { func TestSearchApplicationsGet_WithJobs_ShouldOnlyHaveLatest(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t, true, true) apps := []applicationModels.Application{ {Name: "app-1", Jobs: []*jobModels.JobSummary{ {Name: "app-1-job-1", Started: "2018-11-12T11:45:26Z"}, @@ -537,7 +537,7 @@ func TestSearchApplicationsGet_WithJobs_ShouldOnlyHaveLatest(t *testing.T) { func TestCreateApplication_NoName_ValidationError(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test parameters := buildApplicationRegistrationRequest( @@ -549,12 +549,12 @@ func TestCreateApplication_NoName_ValidationError(t *testing.T) { assert.Equal(t, http.StatusBadRequest, response.Code) errorResponse, _ := controllertest.GetErrorResponse(response) - assert.Equal(t, "Error: app name cannot be empty", errorResponse.Message) + assert.Equal(t, "Error: app name is empty: resource name cannot be empty", errorResponse.Message) } func TestCreateApplication_WhenRequiredConfigurationItemIsNotSet_ReturnError(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test parameters := buildApplicationRegistrationRequest( @@ -569,13 +569,13 @@ func TestCreateApplication_WhenRequiredConfigurationItemIsNotSet_ReturnError(t * assert.Equal(t, http.StatusBadRequest, response.Code) errorResponse, _ := controllertest.GetErrorResponse(response) - expectedError := radixvalidators.ResourceNameCannotBeEmptyError("configuration item") + expectedError := radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("configuration item") assert.Equal(t, fmt.Sprintf("Error: %v", expectedError), errorResponse.Message) } func TestCreateApplication_WhenOptionalConfigurationItemIsNotSet_ReturnSuccess(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(false, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, false, true) // Test parameters := buildApplicationRegistrationRequest( @@ -593,7 +593,7 @@ func TestCreateApplication_WhenOptionalConfigurationItemIsNotSet_ReturnSuccess(t func TestCreateApplication_WhenRequiredAdGroupsIsNotSet_ReturnError(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test parameters := buildApplicationRegistrationRequest( @@ -608,13 +608,13 @@ func TestCreateApplication_WhenRequiredAdGroupsIsNotSet_ReturnError(t *testing.T assert.Equal(t, http.StatusBadRequest, response.Code) errorResponse, _ := controllertest.GetErrorResponse(response) - expectedError := radixvalidators.ResourceNameCannotBeEmptyError("AD groups") + expectedError := radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("AD groups") assert.Equal(t, fmt.Sprintf("Error: %v", expectedError), errorResponse.Message) } func TestCreateApplication_WhenOptionalAdGroupsIsNotSet_ReturnSuccess(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, false) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, false) // Test parameters := buildApplicationRegistrationRequest( @@ -633,7 +633,7 @@ func TestCreateApplication_WhenOptionalAdGroupsIsNotSet_ReturnSuccess(t *testing func TestCreateApplication_WhenConfigBranchIsNotSet_ReturnError(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test parameters := buildApplicationRegistrationRequest( @@ -649,13 +649,13 @@ func TestCreateApplication_WhenConfigBranchIsNotSet_ReturnError(t *testing.T) { assert.Equal(t, http.StatusBadRequest, response.Code) errorResponse, _ := controllertest.GetErrorResponse(response) - expectedError := radixvalidators.ResourceNameCannotBeEmptyError("branch name") + expectedError := radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("branch name") assert.Equal(t, fmt.Sprintf("Error: %v", expectedError), errorResponse.Message) } func TestCreateApplication_WhenConfigBranchIsInvalid_ReturnError(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test configBranch := "main.." @@ -671,7 +671,7 @@ func TestCreateApplication_WhenConfigBranchIsInvalid_ReturnError(t *testing.T) { assert.Equal(t, http.StatusBadRequest, response.Code) errorResponse, _ := controllertest.GetErrorResponse(response) - expectedError := radixvalidators.InvalidConfigBranchName(configBranch) + expectedError := radixvalidators.InvalidConfigBranchNameWithMessage(configBranch) assert.Equal(t, fmt.Sprintf("Error: %v", expectedError), errorResponse.Message) } @@ -699,7 +699,7 @@ func TestCreateApplication_WithRadixConfigFullName(t *testing.T) { for _, scenario := range scenarios { t.Run(fmt.Sprintf("Test for radixConfigFullName: '%s'", scenario.radixConfigFullName), func(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test configBranch := "main" @@ -733,7 +733,7 @@ func TestCreateApplication_WithRadixConfigFullName(t *testing.T) { func TestCreateApplication_DuplicateRepo_ShouldWarn(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -760,14 +760,14 @@ func TestCreateApplication_DuplicateRepo_ShouldWarn(t *testing.T) { assert.Equal(t, http.StatusOK, response.Code) applicationRegistrationUpsertResponse := applicationModels.ApplicationRegistrationUpsertResponse{} err := controllertest.GetResponseBody(response, &applicationRegistrationUpsertResponse) - require.NoError(t, err) + assert.NoError(t, err) assert.NotEmpty(t, applicationRegistrationUpsertResponse.Warnings) assert.Contains(t, applicationRegistrationUpsertResponse.Warnings, "Repository is used in other application(s)") } func TestCreateApplication_DuplicateRepoWithAcknowledgeWarning_ShouldSuccess(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -800,7 +800,7 @@ func TestCreateApplication_DuplicateRepoWithAcknowledgeWarning_ShouldSuccess(t * func TestGetApplication_AllFieldsAreSet(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -824,7 +824,7 @@ func TestGetApplication_AllFieldsAreSet(t *testing.T) { application := applicationModels.Application{} err := controllertest.GetResponseBody(response, &application) - require.NoError(t, err) + assert.NoError(t, err) assert.Equal(t, "https://github.com/Equinor/any-repo", application.Registration.Repository) assert.Equal(t, "Any secret", application.Registration.SharedSecret) @@ -837,7 +837,7 @@ func TestGetApplication_AllFieldsAreSet(t *testing.T) { func TestGetApplication_WithJobs(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t, true, true) _, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration(). WithName("any-name")) require.NoError(t, err) @@ -866,7 +866,7 @@ func TestGetApplication_WithJobs(t *testing.T) { func TestGetApplication_WithEnvironments(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, _, radix, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, _, radix, _, _ := setupTest(t, true, true) anyAppName := "any-app" anyOrphanedEnvironment := "feature" @@ -944,7 +944,7 @@ func TestGetApplication_WithEnvironments(t *testing.T) { func TestUpdateApplication_DuplicateRepo_ShouldWarn(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -989,7 +989,7 @@ func TestUpdateApplication_DuplicateRepo_ShouldWarn(t *testing.T) { func TestUpdateApplication_DuplicateRepoWithAcknowledgeWarnings_ShouldSuccess(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -1036,7 +1036,7 @@ func TestUpdateApplication_DuplicateRepoWithAcknowledgeWarnings_ShouldSuccess(t func TestUpdateApplication_MismatchingNameOrNotExists_ShouldFailAsIllegalOperation(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest(anApplicationRegistration().WithName("any-name").Build(), false) responseChannel := controllerTestUtils.ExecuteRequestWithParameters("POST", "/api/v1/applications", parameters) @@ -1067,7 +1067,7 @@ func TestUpdateApplication_MismatchingNameOrNotExists_ShouldFailAsIllegalOperati func TestUpdateApplication_AbleToSetAnySpecField(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) builder := anApplicationRegistration(). @@ -1142,7 +1142,7 @@ func TestUpdateApplication_AbleToSetAnySpecField(t *testing.T) { func TestModifyApplication_AbleToSetField(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) builder := anApplicationRegistration(). WithName("any-name"). @@ -1277,7 +1277,7 @@ func TestModifyApplication_AbleToSetField(t *testing.T) { func TestModifyApplication_AbleToUpdateRepository(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) builder := anApplicationRegistration(). WithName("any-name"). @@ -1308,7 +1308,7 @@ func TestModifyApplication_AbleToUpdateRepository(t *testing.T) { func TestModifyApplication_ConfigBranchSetToFallbackHack(t *testing.T) { // Setup appName := "any-name" - _, controllerTestUtils, _, radixClient, _, _ := setupTest(true, true) + _, controllerTestUtils, _, radixClient, _, _ := setupTest(t, true, true) rr := builders.ARadixRegistration(). WithName(appName). WithConfigurationItem("any"). @@ -1338,7 +1338,7 @@ func TestModifyApplication_ConfigBranchSetToFallbackHack(t *testing.T) { func TestModifyApplication_IgnoreRequireCIValidationWhenRequiredButCurrentIsEmpty(t *testing.T) { // Setup - _, controllerTestUtils, _, radixClient, _, _ := setupTest(true, true) + _, controllerTestUtils, _, radixClient, _, _ := setupTest(t, true, true) rr, err := anApplicationRegistration(). WithName("any-name"). @@ -1362,7 +1362,7 @@ func TestModifyApplication_IgnoreRequireCIValidationWhenRequiredButCurrentIsEmpt func TestModifyApplication_IgnoreRequireADGroupValidationWhenRequiredButCurrentIsEmpty(t *testing.T) { // Setup - _, controllerTestUtils, _, radixClient, _, _ := setupTest(true, true) + _, controllerTestUtils, _, radixClient, _, _ := setupTest(t, true, true) rr, err := anApplicationRegistration(). WithName("any-name"). @@ -1453,7 +1453,7 @@ func TestModifyApplication_UpdateADGroupValidation(t *testing.T) { for _, ts := range scenarios { t.Run(ts.name, func(t *testing.T) { - _, controllerTestUtils, _, radixClient, _, _ := setupTestWithFactory(newTestApplicationHandlerFactory( + _, controllerTestUtils, _, radixClient, _, _ := setupTestWithFactory(t, newTestApplicationHandlerFactory( ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: ts.requireAppADGroups}, func(ctx context.Context, kubeClient kubernetes.Interface, namespace string, configMapName string) (bool, error) { return ts.hasAccessToAdGroups, nil @@ -1484,7 +1484,7 @@ func TestModifyApplication_UpdateADGroupValidation(t *testing.T) { func TestHandleTriggerPipeline_ForNonMappedAndMappedAndMagicBranchEnvironment_JobIsNotCreatedForUnmapped(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) anyAppName := "any-app" configBranch := "magic" @@ -1527,7 +1527,7 @@ func TestHandleTriggerPipeline_ForNonMappedAndMappedAndMagicBranchEnvironment_Jo func TestHandleTriggerPipeline_ExistingAndNonExistingApplication_JobIsCreatedForExisting(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) registerAppParam := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -1598,7 +1598,7 @@ func TestHandleTriggerPipeline_Deploy_JobHasCorrectParameters(t *testing.T) { for _, ts := range scenarios { t.Run(ts.name, func(t *testing.T) { - _, controllerTestUtils, _, radixclient, _, _ := setupTest(true, true) + _, controllerTestUtils, _, radixclient, _, _ := setupTest(t, true, true) registerAppParam := buildApplicationRegistrationRequest(anApplicationRegistration().WithName(appName).Build(), false) <-controllerTestUtils.ExecuteRequestWithParameters("POST", "/api/v1/applications", registerAppParam) responseChannel := controllerTestUtils.ExecuteRequestWithParameters("POST", fmt.Sprintf("/api/v1/applications/%s/pipelines/%s", appName, v1.Deploy), ts.params) @@ -1614,7 +1614,7 @@ func TestHandleTriggerPipeline_Deploy_JobHasCorrectParameters(t *testing.T) { } func TestHandleTriggerPipeline_Promote_JobHasCorrectParameters(t *testing.T) { - commonTestUtils, controllerTestUtils, _, radixclient, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, _, radixclient, _, _ := setupTest(t, true, true) const ( appName = "an-app" @@ -1656,7 +1656,7 @@ func TestHandleTriggerPipeline_Promote_JobHasCorrectParameters(t *testing.T) { func TestIsDeployKeyValid(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t, true, true) _, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration(). WithName("some-app"). WithPublicKey("some-public-key"). @@ -1726,7 +1726,7 @@ func TestIsDeployKeyValid(t *testing.T) { func TestDeleteApplication_ApplicationIsDeleted(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) parameters := buildApplicationRegistrationRequest( anApplicationRegistration(). @@ -1755,7 +1755,7 @@ func TestDeleteApplication_ApplicationIsDeleted(t *testing.T) { func TestGetApplication_WithAppAlias_ContainsAppAlias(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretproviderclient := setupTest(true, true) + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretproviderclient := setupTest(t, true, true) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretproviderclient, builders.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("prod"). @@ -1787,7 +1787,7 @@ func TestListPipeline_ReturnesAvailablePipelines(t *testing.T) { supportedPipelines := jobPipeline.GetSupportedPipelines() // Setup - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) _, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration(). WithName("some-app"). WithPublicKey("some-public-key"). @@ -1806,7 +1806,7 @@ func TestListPipeline_ReturnesAvailablePipelines(t *testing.T) { func TestRegenerateDeployKey_WhenApplicationNotExist_Fail(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest(true, true) + _, controllerTestUtils, _, _, _, _ := setupTest(t, true, true) // Test parameters := buildApplicationRegistrationRequest( @@ -1835,7 +1835,7 @@ func TestRegenerateDeployKey_WhenApplicationNotExist_Fail(t *testing.T) { func TestRegenerateDeployKey_NoSecretInParam_SecretIsReCreated(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeUtil, radixClient, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeUtil, radixClient, _, _ := setupTest(t, true, true) appName := "any-name" rrBuilder := builders.ARadixRegistration().WithName(appName).WithCloneURL("git@github.com:Equinor/my-app.git") @@ -1867,7 +1867,7 @@ func TestRegenerateDeployKey_NoSecretInParam_SecretIsReCreated(t *testing.T) { func TestRegenerateDeployKey_PrivateKeyInParam_SavedPrivateKeyIsEqualToWebParam(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeUtil, radixClient, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeUtil, radixClient, _, _ := setupTest(t, true, true) appName := "any-name" rrBuilder := builders.ARadixRegistration().WithName(appName).WithCloneURL("git@github.com:Equinor/my-app.git") @@ -1897,7 +1897,7 @@ func TestRegenerateDeployKey_PrivateKeyInParam_SavedPrivateKeyIsEqualToWebParam( func TestRegenerateDeployKey_InvalidKeyInParam_ErrorIsReturned(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeUtil, radixClient, _, _ := setupTest(true, true) + commonTestUtils, controllerTestUtils, kubeUtil, radixClient, _, _ := setupTest(t, true, true) appName := "any-name" rrBuilder := builders.ARadixRegistration().WithName(appName).WithCloneURL("git@github.com:Equinor/my-app.git") diff --git a/api/applications/applications_handler.go b/api/applications/applications_handler.go index 28212af9..c60a44e5 100644 --- a/api/applications/applications_handler.go +++ b/api/applications/applications_handler.go @@ -15,7 +15,6 @@ import ( jobModels "github.com/equinor/radix-api/api/jobs/models" "github.com/equinor/radix-api/api/kubequery" apimodels "github.com/equinor/radix-api/api/models" - "github.com/equinor/radix-api/api/utils" "github.com/equinor/radix-api/models" radixhttp "github.com/equinor/radix-common/net/http" radixutils "github.com/equinor/radix-common/utils" @@ -117,7 +116,11 @@ func (ah *ApplicationHandler) GetApplication(ctx context.Context, appName string return nil, err } - application := apimodels.BuildApplication(rr, ra, reList, rdList, rjList, ingressList, userIsAdmin) + radixDNSAliasList, err := kubequery.GetRadixDNSAliases(ctx, ah.accounts.UserAccount.RadixClient, appName) + if err != nil { + return nil, err + } + application := apimodels.BuildApplication(rr, ra, reList, rdList, rjList, ingressList, userIsAdmin, radixDNSAliasList, ah.config.DNSZone) return application, nil } @@ -508,13 +511,12 @@ func (ah *ApplicationHandler) triggerPipelineBuildOrBuildDeploy(ctx context.Cont // Check if branch is mapped if !applicationconfig.IsConfigBranch(branch, radixRegistration) { - application, err := utils.CreateApplicationConfig(ctx, &userAccount, appName) + ra, err := userAccount.RadixClient.RadixV1().RadixApplications(operatorUtils.GetAppNamespace(appName)).Get(ctx, appName, metav1.GetOptions{}) if err != nil { return nil, err } - isThereAnythingToDeploy, _ := application.IsThereAnythingToDeploy(branch) - - if !isThereAnythingToDeploy { + targetEnvironments := applicationconfig.GetTargetEnvironments(branch, ra) + if len(targetEnvironments) == 0 { return nil, applicationModels.UnmatchedBranchToEnvironment(branch) } } @@ -746,9 +748,9 @@ func createRoleBindingForRole(ctx context.Context, kubeClient kubernetes.Interfa var subjects []rbacv1.Subject for _, adGroup := range adGroups { subjects = append(subjects, rbacv1.Subject{ - Kind: k8s.KindGroup, + Kind: rbacv1.GroupKind, Name: adGroup, - APIGroup: k8s.RbacApiGroup, + APIGroup: rbacv1.GroupName, }) } newRoleBinding := &rbacv1.RoleBinding{ @@ -757,7 +759,7 @@ func createRoleBindingForRole(ctx context.Context, kubeClient kubernetes.Interfa Labels: labels, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindRole, Name: role.GetName(), UID: role.GetUID(), @@ -765,7 +767,7 @@ func createRoleBindingForRole(ctx context.Context, kubeClient kubernetes.Interfa }, }, RoleRef: rbacv1.RoleRef{ - APIGroup: k8s.RbacApiGroup, + APIGroup: rbacv1.GroupName, Kind: k8s.KindRole, Name: role.GetName(), }, Subjects: subjects, diff --git a/api/applications/applications_handler_config.go b/api/applications/applications_handler_config.go index cbb74b58..87c749a2 100644 --- a/api/applications/applications_handler_config.go +++ b/api/applications/applications_handler_config.go @@ -31,6 +31,7 @@ type ApplicationHandlerConfig struct { RequireAppADGroups bool `cfg:"require_app_ad_groups" flag:"require-app-ad-groups"` AppName string `cfg:"radix_app" flag:"radix-app"` EnvironmentName string `cfg:"radix_environment" flag:"radix-environment"` + DNSZone string `cfg:"radix_dns_zone" flag:"radix-dns-zone"` } func ApplicationHandlerConfigFlagSet() *pflag.FlagSet { @@ -40,5 +41,6 @@ func ApplicationHandlerConfigFlagSet() *pflag.FlagSet { flagset.Bool("require-app-ad-groups", true, "Require AD groups for application") flagset.String("radix-app", "", "Application name") flagset.String("radix-environment", "", "Environment name") + flagset.String("radix-dns-zone", "", "Radix DNS zone") return flagset } diff --git a/api/applications/models/application.go b/api/applications/models/application.go index d0dbc0f0..7328d786 100644 --- a/api/applications/models/application.go +++ b/api/applications/models/application.go @@ -29,6 +29,11 @@ type Application struct { // required: false Jobs []*jobModels.JobSummary `json:"jobs"` + // DNS aliases showing nicer endpoint for application, without "app." subdomain domain + // + // required: false + DNSAliases []DNSAlias `json:"dnsAliases,omitempty"` + // App alias showing nicer endpoint for application // // required: false diff --git a/api/applications/models/dns_alias.go b/api/applications/models/dns_alias.go new file mode 100644 index 00000000..51ff2def --- /dev/null +++ b/api/applications/models/dns_alias.go @@ -0,0 +1,32 @@ +package models + +// DNSAlias holds public DNS alias information +// swagger:model DNSAlias +type DNSAlias struct { + // URL the public endpoint + // + // required: true + // example: https://my-app.radix.equinor.com + URL string `json:"url"` + + // ComponentName the component exposing the endpoint + // + // required: true + // example: frontend + ComponentName string `json:"componentName"` + + // EnvironmentName the environment hosting the endpoint + // + // required: true + // example: prod + EnvironmentName string `json:"environmentName"` + + Status DNSAliasStatus `json:"status,omitempty"` +} + +// DNSAliasStatus Status of the DNSAlias +// swagger:model DNSAliasStatus +type DNSAliasStatus struct { + Condition string `json:"condition,omitempty"` + Message string `json:"message,omitempty"` +} diff --git a/api/buildsecrets/buildsecrets_test.go b/api/buildsecrets/buildsecrets_test.go index d7686837..dd2a138e 100644 --- a/api/buildsecrets/buildsecrets_test.go +++ b/api/buildsecrets/buildsecrets_test.go @@ -28,7 +28,7 @@ const ( subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" ) -func setupTest() (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface) { +func setupTest(t *testing.T) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface) { // Setup kubeclient := kubefake.NewSimpleClientset() radixclient := fake.NewSimpleClientset() @@ -36,8 +36,8 @@ func setupTest() (*commontest.Utils, *controllertest.Utils, kubernetes.Interface // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) - + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) // controllerTestUtils is used for issuing HTTP request and processing responses controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewBuildSecretsController()) @@ -50,7 +50,7 @@ func TestGetBuildSecrets_ListsAll(t *testing.T) { anyBuildSecret3 := "secret3" // Setup - commonTestUtils, controllerTestUtils, client, radixclient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient := setupTest(t) err := utils.ApplyApplicationWithSync(client, radixclient, commonTestUtils, builders.ARadixApplication(). @@ -107,7 +107,7 @@ func TestUpdateBuildSecret_UpdatedOk(t *testing.T) { anyBuildSecret1 := "secret1" // Setup - commonTestUtils, controllerTestUtils, client, radixclient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient := setupTest(t) err := utils.ApplyApplicationWithSync(client, radixclient, commonTestUtils, builders.ARadixApplication(). diff --git a/api/buildstatus/build_status_controller_test.go b/api/buildstatus/build_status_controller_test.go index dcc974cb..fbbca4fd 100644 --- a/api/buildstatus/build_status_controller_test.go +++ b/api/buildstatus/build_status_controller_test.go @@ -23,14 +23,12 @@ import ( ) const ( - clusterName = "AnyClusterName" - dnsZone = "dev.radix.equinor.com" - appAliasDNSZone = "app.dev.radix.equinor.com" - egressIps = "0.0.0.0" - subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" + clusterName = "AnyClusterName" + egressIps = "0.0.0.0" + subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" ) -func setupTest() (*commontest.Utils, *kubefake.Clientset, *fake.Clientset, *secretproviderfake.Clientset) { +func setupTest(t *testing.T) (*commontest.Utils, *kubefake.Clientset, *fake.Clientset, *secretproviderfake.Clientset) { // Setup kubeclient := kubefake.NewSimpleClientset() radixclient := fake.NewSimpleClientset() @@ -38,14 +36,15 @@ func setupTest() (*commontest.Utils, *kubefake.Clientset, *fake.Clientset, *secr // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) _ = os.Setenv(defaults.ActiveClusternameEnvironmentVariable, clusterName) return &commonTestUtils, kubeclient, radixclient, secretproviderclient } func TestGetBuildStatus(t *testing.T) { - commonTestUtils, kubeclient, radixclient, secretproviderclient := setupTest() + commonTestUtils, kubeclient, radixclient, secretproviderclient := setupTest(t) jobStartReferenceTime := time.Date(2020, 1, 10, 0, 0, 0, 0, time.UTC) _, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration()) diff --git a/api/defaults/environment_variables.go b/api/defaults/environment_variables.go new file mode 100644 index 00000000..aedaa91c --- /dev/null +++ b/api/defaults/environment_variables.go @@ -0,0 +1,6 @@ +package defaults + +const ( + // RadixDNSZoneEnvironmentVariable The environment variable on a radix app giving the dns zone. Will be equal to OperatorDNSZoneEnvironmentVariable + RadixDNSZoneEnvironmentVariable = "RADIX_DNS_ZONE" +) diff --git a/api/deployments/component_controller_test.go b/api/deployments/component_controller_test.go index e296e03c..66f20377 100644 --- a/api/deployments/component_controller_test.go +++ b/api/deployments/component_controller_test.go @@ -30,7 +30,7 @@ func createGetComponentsEndpoint(appName, deployName string) string { func TestGetComponents_non_existing_app(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest() + _, controllerTestUtils, _, _, _, _ := setupTest(t) endpoint := createGetComponentsEndpoint(anyAppName, anyDeployName) @@ -43,7 +43,7 @@ func TestGetComponents_non_existing_app(t *testing.T) { } func TestGetComponents_non_existing_deployment(t *testing.T) { - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyApplication(operatorUtils. ARadixApplication(). WithAppName(anyAppName)) @@ -63,7 +63,7 @@ func TestGetComponents_non_existing_deployment(t *testing.T) { func TestGetComponents_active_deployment(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(operatorUtils. ARadixDeployment(). WithJobComponents( @@ -102,7 +102,7 @@ func TestGetComponents_active_deployment(t *testing.T) { func TestGetComponents_WithExternalAlias_ContainsTLSSecrets(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorUtils.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("prod"). @@ -139,7 +139,7 @@ func TestGetComponents_WithExternalAlias_ContainsTLSSecrets(t *testing.T) { func TestGetComponents_WithVolumeMount_ContainsVolumeMountSecrets(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorUtils.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("prod"). @@ -198,7 +198,7 @@ func TestGetComponents_WithVolumeMount_ContainsVolumeMountSecrets(t *testing.T) func TestGetComponents_WithTwoVolumeMounts_ContainsTwoVolumeMountSecrets(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorUtils.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("prod"). @@ -247,7 +247,7 @@ func TestGetComponents_WithTwoVolumeMounts_ContainsTwoVolumeMountSecrets(t *test func TestGetComponents_OAuth2(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorUtils.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("prod"). @@ -292,7 +292,7 @@ func TestGetComponents_OAuth2(t *testing.T) { func TestGetComponents_inactive_deployment(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) initialDeploymentCreated, _ := radixutils.ParseTimestamp("2018-11-12T11:45:26Z") activeDeploymentCreated, _ := radixutils.ParseTimestamp("2018-11-14T11:45:26Z") @@ -372,7 +372,7 @@ func getPodSpec(podName, radixComponentLabel string) *corev1.Pod { func TestGetComponents_success(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(operatorUtils. ARadixDeployment(). WithAppName(anyAppName). @@ -397,7 +397,7 @@ func TestGetComponents_success(t *testing.T) { func TestGetComponents_ReplicaStatus_Failing(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(operatorUtils. ARadixDeployment(). WithAppName(anyAppName). @@ -443,7 +443,7 @@ func TestGetComponents_ReplicaStatus_Failing(t *testing.T) { func TestGetComponents_ReplicaStatus_Running(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(operatorUtils. ARadixDeployment(). WithAppName(anyAppName). @@ -488,7 +488,7 @@ func TestGetComponents_ReplicaStatus_Running(t *testing.T) { func TestGetComponents_ReplicaStatus_Starting(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(operatorUtils. ARadixDeployment(). WithAppName(anyAppName). @@ -533,7 +533,7 @@ func TestGetComponents_ReplicaStatus_Starting(t *testing.T) { func TestGetComponents_ReplicaStatus_Pending(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(operatorUtils. ARadixDeployment(). WithAppName(anyAppName). @@ -579,7 +579,7 @@ func TestGetComponents_ReplicaStatus_Pending(t *testing.T) { func TestGetComponents_WithHorizontalScaling(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t) testScenarios := []struct { name string deploymentName string @@ -634,7 +634,7 @@ func TestGetComponents_WithHorizontalScaling(t *testing.T) { func TestGetComponents_WithIdentity(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest() + commonTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorUtils.ARadixDeployment(). WithAppName("any-app"). diff --git a/api/deployments/component_handler.go b/api/deployments/component_handler.go index 2b891caf..8a298d62 100644 --- a/api/deployments/component_handler.go +++ b/api/deployments/component_handler.go @@ -5,9 +5,9 @@ import ( "strings" deploymentModels "github.com/equinor/radix-api/api/deployments/models" + "github.com/equinor/radix-api/api/utils" "github.com/equinor/radix-api/api/utils/labelselector" radixutils "github.com/equinor/radix-common/utils" - configUtils "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -76,7 +76,7 @@ func (deploy *deployHandler) getComponent(ctx context.Context, component v1.Radi envNs := crdUtils.GetEnvironmentNamespace(ra.Name, deployment.Environment) // TODO: Add interface for RA + EnvConfig - environmentConfig := configUtils.GetComponentEnvironmentConfig(ra, deployment.Environment, component.GetName()) + environmentConfig := utils.GetComponentEnvironmentConfig(ra, deployment.Environment, component.GetName()) deploymentComponent, err := GetComponentStateFromSpec(ctx, deploy.accounts.UserAccount.Client, ra.Name, deployment, rd.Status, environmentConfig, component) if err != nil { diff --git a/api/deployments/deployment_controller_test.go b/api/deployments/deployment_controller_test.go index a09534c7..e875cceb 100644 --- a/api/deployments/deployment_controller_test.go +++ b/api/deployments/deployment_controller_test.go @@ -34,16 +34,15 @@ func createGetLogEndpoint(appName, podName string) string { return fmt.Sprintf("/api/v1/applications/%s/deployments/any/components/any/replicas/%s/logs", appName, podName) } -func setupTest() (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, - prometheusclient.Interface, secretsstorevclient.Interface) { - commonTestUtils, kubeclient, radixClient, prometheusClient, secretproviderclient := apiUtils.SetupTest() +func setupTest(t *testing.T) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { + commonTestUtils, kubeclient, radixClient, prometheusClient, secretproviderclient := apiUtils.SetupTest(t) // controllerTestUtils is used for issuing HTTP request and processing responses controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixClient, secretproviderclient, NewDeploymentController()) return commonTestUtils, &controllerTestUtils, kubeclient, radixClient, prometheusClient, secretproviderclient } func TestGetPodLog_no_radixconfig(t *testing.T) { // Setup - _, controllerTestUtils, _, _, _, _ := setupTest() + _, controllerTestUtils, _, _, _, _ := setupTest(t) endpoint := createGetLogEndpoint(anyAppName, anyPodName) @@ -57,7 +56,7 @@ func TestGetPodLog_no_radixconfig(t *testing.T) { } func TestGetPodLog_No_Pod(t *testing.T) { - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) endpoint := createGetLogEndpoint(anyAppName, anyPodName) _, err := commonTestUtils.ApplyApplication(builders. @@ -78,7 +77,7 @@ func TestGetPodLog_No_Pod(t *testing.T) { func TestGetDeployments_Filter_FilterIsApplied(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) _, err := commonTestUtils.ApplyDeployment(builders. ARadixDeployment(). @@ -165,7 +164,7 @@ func TestGetDeployments_Filter_FilterIsApplied(t *testing.T) { } func TestGetDeployments_NoApplicationRegistered(t *testing.T) { - _, controllerTestUtils, _, _, _, _ := setupTest() + _, controllerTestUtils, _, _, _, _ := setupTest(t) responseChannel := controllerTestUtils.ExecuteRequest("GET", fmt.Sprintf("/api/v1/applications/%s/deployments", anyAppName)) response := <-responseChannel @@ -189,7 +188,7 @@ func TestGetDeployments_OneEnvironment_SortedWithFromTo(t *testing.T) { annotations := make(map[string]string) annotations[kube.RadixGitTagsAnnotation] = gitTags annotations[kube.RadixCommitAnnotation] = gitCommitHash - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) err := setupGetDeploymentsTest(commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, []string{"dev"}, annotations) require.NoError(t, err) @@ -229,7 +228,7 @@ func TestGetDeployments_OneEnvironment_Latest(t *testing.T) { annotations := make(map[string]string) annotations[kube.RadixGitTagsAnnotation] = "some tags go here" annotations[kube.RadixCommitAnnotation] = "gfsjrgnsdkfgnlnfgdsMYCOMMIT" - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) err := setupGetDeploymentsTest(commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, []string{"dev"}, annotations) require.NoError(t, err) @@ -259,7 +258,7 @@ func TestGetDeployments_TwoEnvironments_SortedWithFromTo(t *testing.T) { annotations := make(map[string]string) annotations[kube.RadixGitTagsAnnotation] = "some tags go here" annotations[kube.RadixCommitAnnotation] = "gfsjrgnsdkfgnlnfgdsMYCOMMIT" - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) err := setupGetDeploymentsTest(commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, []string{"dev", "prod"}, annotations) require.NoError(t, err) @@ -297,7 +296,7 @@ func TestGetDeployments_TwoEnvironments_Latest(t *testing.T) { annotations := make(map[string]string) annotations[kube.RadixGitTagsAnnotation] = "some tags go here" annotations[kube.RadixCommitAnnotation] = "gfsjrgnsdkfgnlnfgdsMYCOMMIT" - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) err := setupGetDeploymentsTest(commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, []string{"dev", "prod"}, annotations) require.NoError(t, err) @@ -319,7 +318,7 @@ func TestGetDeployments_TwoEnvironments_Latest(t *testing.T) { } func TestGetDeployment_NoApplicationRegistered(t *testing.T) { - _, controllerTestUtils, _, _, _, _ := setupTest() + _, controllerTestUtils, _, _, _, _ := setupTest(t) responseChannel := controllerTestUtils.ExecuteRequest("GET", fmt.Sprintf("/api/v1/applications/%s/deployments/%s", anyAppName, anyDeployName)) response := <-responseChannel @@ -330,7 +329,7 @@ func TestGetDeployment_NoApplicationRegistered(t *testing.T) { func TestGetDeployment_TwoDeploymentsFirstDeployment_ReturnsDeploymentWithComponents(t *testing.T) { // Setup - commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, _, _, _, _ := setupTest(t) anyAppName := "any-app" anyEnvironment := "dev" anyDeployment1Name := "abcdef" diff --git a/api/deployments/models/component_builder.go b/api/deployments/models/component_builder.go index ad33a6fd..61721ae3 100644 --- a/api/deployments/models/component_builder.go +++ b/api/deployments/models/component_builder.go @@ -1,11 +1,13 @@ package models import ( + "errors" + "github.com/equinor/radix-api/api/secrets/suffix" "github.com/equinor/radix-api/api/utils/secret" - errorutils "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" + "github.com/equinor/radix-operator/pkg/apis/ingress" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" ) @@ -136,7 +138,7 @@ func (b *componentBuilder) WithComponent(component v1.RadixCommonDeployComponent } if auth := component.GetAuthentication(); auth != nil && component.IsPublic() { - if deployment.IsSecretRequiredForClientCertificate(auth.ClientCertificate) { + if ingress.IsSecretRequiredForClientCertificate(auth.ClientCertificate) { b.secrets = append(b.secrets, utils.GetComponentClientCertificateSecretName(component.GetName())) } if auth.OAuth2 != nil { @@ -192,7 +194,7 @@ func (b *componentBuilder) buildError() error { return nil } - return errorutils.Concat(b.errors) + return errors.Join(b.errors...) } func (b *componentBuilder) BuildComponentSummary() (*ComponentSummary, error) { diff --git a/api/deployments/models/deployment_builder.go b/api/deployments/models/deployment_builder.go index 9c2665d7..fe43b425 100644 --- a/api/deployments/models/deployment_builder.go +++ b/api/deployments/models/deployment_builder.go @@ -1,12 +1,12 @@ package models import ( + "errors" "time" crdUtils "github.com/equinor/radix-operator/pkg/apis/utils" radixutils "github.com/equinor/radix-common/utils" - errorutils "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" ) @@ -147,7 +147,7 @@ func (b *deploymentBuilder) buildError() error { return nil } - return errorutils.Concat(b.errors) + return errors.Join(b.errors...) } func (b *deploymentBuilder) BuildDeploymentSummary() (*DeploymentSummary, error) { diff --git a/api/environments/environment_controller_secrets_test.go b/api/environments/environment_controller_secrets_test.go index 10b84355..a338a7ad 100644 --- a/api/environments/environment_controller_secrets_test.go +++ b/api/environments/environment_controller_secrets_test.go @@ -870,7 +870,7 @@ func (s *externalDnsAliasSecretTestSuite) buildCertificate(certCN, issuerCN stri func (s *externalDnsAliasSecretTestSuite) SetupTest() { ctrl := gomock.NewController(s.T()) s.tlsValidator = tlsvalidatormock.NewMockTLSSecretValidator(ctrl) - s.commonTestUtils, s.envvironmentTestUtils, _, s.kubeClient, s.radixClient, _, s.secretProviderClient = setupTest([]EnvironmentHandlerOptions{WithTLSSecretValidator(s.tlsValidator)}) + s.commonTestUtils, s.envvironmentTestUtils, _, s.kubeClient, s.radixClient, _, s.secretProviderClient = setupTest(s.T(), []EnvironmentHandlerOptions{WithTLSSecretValidator(s.tlsValidator)}) s.appName, s.componentName, s.environmentName, s.alias = "any-app", "backend", "dev", "cdn.myalias.com" @@ -1226,7 +1226,7 @@ func (s *secretHandlerTestSuite) assertSecrets(scenario *getSecretScenario, secr } func (s *secretHandlerTestSuite) prepareTestRun(scenario *getSecretScenario, appName, envName, deploymentName string) *controllertest.Utils { - _, environmentControllerTestUtils, _, kubeClient, radixClient, _, secretClient := setupTest(nil) + _, environmentControllerTestUtils, _, kubeClient, radixClient, _, secretClient := setupTest(s.T(), nil) _, err := radixClient.RadixV1().RadixRegistrations().Create(context.Background(), &v1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}}, metav1.CreateOptions{}) require.NoError(s.T(), err) appAppNamespace := operatorutils.GetAppNamespace(appName) diff --git a/api/environments/environment_controller_test.go b/api/environments/environment_controller_test.go index 718018de..d3252419 100644 --- a/api/environments/environment_controller_test.go +++ b/api/environments/environment_controller_test.go @@ -62,7 +62,7 @@ const ( subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" ) -func setupTest(envHandlerOpts []EnvironmentHandlerOptions) (*commontest.Utils, *controllertest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { +func setupTest(t *testing.T, envHandlerOpts []EnvironmentHandlerOptions) (*commontest.Utils, *controllertest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { // Setup kubeclient := kubefake.NewSimpleClientset() radixclient := fake.NewSimpleClientset() @@ -71,7 +71,8 @@ func setupTest(envHandlerOpts []EnvironmentHandlerOptions) (*commontest.Utils, * // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) // secretControllerTestUtils is used for issuing HTTP request and processing responses secretControllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, secrets.NewSecretController()) @@ -91,7 +92,7 @@ func TestGetEnvironmentDeployments_SortedWithFromTo(t *testing.T) { deploymentThreeCreated, _ := time.Parse(layout, "2018-11-20T09:00:00.000Z") // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) setupGetDeploymentsTest(t, commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, anyEnvironment) responseChannel := environmentControllerTestUtils.ExecuteRequest("GET", fmt.Sprintf("/api/v1/applications/%s/environments/%s/deployments", anyAppName, anyEnvironment)) @@ -125,7 +126,7 @@ func TestGetEnvironmentDeployments_Latest(t *testing.T) { deploymentThreeCreated, _ := time.Parse(layout, "2018-11-20T09:00:00.000Z") // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) setupGetDeploymentsTest(t, commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, anyEnvironment) responseChannel := environmentControllerTestUtils.ExecuteRequest("GET", fmt.Sprintf("/api/v1/applications/%s/environments/%s/deployments?latest=true", anyAppName, anyEnvironment)) @@ -145,7 +146,7 @@ func TestGetEnvironmentSummary_ApplicationWithNoDeployments_EnvironmentPending(t envName1, envName2 := "dev", "master" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. NewRadixApplicationBuilder(). WithRadixRegistration(operatorutils.ARadixRegistration()). @@ -169,7 +170,7 @@ func TestGetEnvironmentSummary_ApplicationWithNoDeployments_EnvironmentPending(t func TestGetEnvironmentSummary_ApplicationWithDeployment_EnvironmentConsistent(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyDeployment(operatorutils. ARadixDeployment(). WithRadixApplication(operatorutils. @@ -203,7 +204,7 @@ func TestGetEnvironmentSummary_RemoveEnvironmentFromConfig_OrphanedEnvironment(t anyOrphanedEnvironment := "feature-1" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -253,7 +254,7 @@ func TestGetEnvironmentSummary_OrphanedEnvironmentWithDash_OrphanedEnvironmentIs anyOrphanedEnvironment := "feature-1" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) rr, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -298,7 +299,7 @@ func TestDeleteEnvironment_OneOrphanedEnvironment_OnlyOrphanedCanBeDeleted(t *te anyOrphanedEnvironment := "feature-1" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. NewRadixApplicationBuilder(). WithAppName(anyAppName). @@ -352,7 +353,7 @@ func TestGetEnvironment_NoExistingEnvironment_ReturnsAnError(t *testing.T) { anyNonExistingEnvironment := "non-existing-environment" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. ARadixApplication(). WithAppName(anyAppName). @@ -372,7 +373,7 @@ func TestGetEnvironment_NoExistingEnvironment_ReturnsAnError(t *testing.T) { func TestGetEnvironment_ExistingEnvironmentInConfig_ReturnsAPendingEnvironment(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. ARadixApplication(). WithAppName(anyAppName). @@ -438,7 +439,7 @@ func TestRestartComponent_ApplicationWithDeployment_EnvironmentConsistent(t *tes stoppedComponent, startedComponent := "stoppedComponent", "startedComponent" // Setup - commonTestUtils, environmentControllerTestUtils, _, client, radixclient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, client, radixclient, _, _ := setupTest(t, nil) rd, _ := createRadixDeploymentWithReplicas(commonTestUtils, anyAppName, anyEnvironment, []ComponentCreatorStruct{ {name: stoppedComponent, number: 0}, {name: startedComponent, number: 1}, @@ -495,7 +496,7 @@ func TestStartComponent_ApplicationWithDeployment_EnvironmentConsistent(t *testi stoppedComponent1, stoppedComponent2 := "stoppedComponent1", "stoppedComponent2" // Setup - commonTestUtils, environmentControllerTestUtils, _, client, radixclient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, client, radixclient, _, _ := setupTest(t, nil) rd, _ := createRadixDeploymentWithReplicas(commonTestUtils, anyAppName, anyEnvironment, []ComponentCreatorStruct{ {name: stoppedComponent1, number: 0}, {name: stoppedComponent2, number: 0}, @@ -543,7 +544,7 @@ func TestStopComponent_ApplicationWithDeployment_EnvironmentConsistent(t *testin runningComponent, stoppedComponent := "runningComp", "stoppedComponent" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(t, nil) rd, _ := createRadixDeploymentWithReplicas(commonTestUtils, anyAppName, anyEnvironment, []ComponentCreatorStruct{ {name: runningComponent, number: 3}, {name: stoppedComponent, number: 0}, @@ -588,7 +589,7 @@ func TestRestartEnvrionment_ApplicationWithDeployment_EnvironmentConsistent(t *t zeroReplicas := 0 // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(t, nil) // Test t.Run("Restart Environment", func(t *testing.T) { @@ -643,7 +644,7 @@ func TestStartEnvrionment_ApplicationWithDeployment_EnvironmentConsistent(t *tes zeroReplicas := 0 // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(t, nil) // Test t.Run("Start Environment", func(t *testing.T) { @@ -698,7 +699,7 @@ func TestStopEnvrionment_ApplicationWithDeployment_EnvironmentConsistent(t *test zeroReplicas := 0 // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixclient, _, _ := setupTest(t, nil) // Test t.Run("Stop Environment", func(t *testing.T) { @@ -749,7 +750,7 @@ func TestStopEnvrionment_ApplicationWithDeployment_EnvironmentConsistent(t *test func TestCreateEnvironment(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. ARadixApplication(). WithAppName(anyAppName)) @@ -765,7 +766,7 @@ func Test_GetEnvironmentEvents_Controller(t *testing.T) { envName := "dev" // Setup - commonTestUtils, environmentControllerTestUtils, _, kubeClient, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, kubeClient, _, _, _ := setupTest(t, nil) createEvent := func(namespace, eventName string) { _, err := kubeClient.CoreV1().Events(namespace).CreateWithEventNamespace(&corev1.Event{ ObjectMeta: metav1.ObjectMeta{ @@ -820,7 +821,7 @@ func Test_GetEnvironmentEvents_Controller(t *testing.T) { // secret tests func TestUpdateSecret_TLSSecretForExternalAlias_UpdatedOk(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretproviderclient := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretproviderclient := setupTest(t, nil) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretproviderclient, operatorutils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). @@ -867,7 +868,7 @@ func TestUpdateSecret_TLSSecretForExternalAlias_UpdatedOk(t *testing.T) { func TestUpdateSecret_AccountSecretForComponentVolumeMount_UpdatedOk(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t, nil) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorutils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). @@ -908,7 +909,7 @@ func TestUpdateSecret_AccountSecretForComponentVolumeMount_UpdatedOk(t *testing. func TestUpdateSecret_AccountSecretForJobVolumeMount_UpdatedOk(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t, nil) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorutils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). @@ -948,7 +949,7 @@ func TestUpdateSecret_AccountSecretForJobVolumeMount_UpdatedOk(t *testing.T) { func TestUpdateSecret_OAuth2_UpdatedOk(t *testing.T) { // Setup envNs := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) - commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, controllerTestUtils, client, radixclient, promclient, secretProviderClient := setupTest(t, nil) err := utils.ApplyDeploymentWithSync(client, radixclient, promclient, commonTestUtils, secretProviderClient, operatorutils.NewDeploymentBuilder(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). @@ -1027,7 +1028,7 @@ func TestGetSecretDeployments_SortedWithFromTo(t *testing.T) { deploymentThreeCreated, _ := time.Parse(layout, "2018-11-20T09:00:00.000Z") // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) setupGetDeploymentsTest(t, commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, anyEnvironment) responseChannel := environmentControllerTestUtils.ExecuteRequest("GET", fmt.Sprintf("/api/v1/applications/%s/environments/%s/deployments", anyAppName, anyEnvironment)) @@ -1061,7 +1062,7 @@ func TestGetSecretDeployments_Latest(t *testing.T) { deploymentThreeCreated, _ := time.Parse(layout, "2018-11-20T09:00:00.000Z") // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) setupGetDeploymentsTest(t, commonTestUtils, anyAppName, deploymentOneImage, deploymentTwoImage, deploymentThreeImage, deploymentOneCreated, deploymentTwoCreated, deploymentThreeCreated, anyEnvironment) responseChannel := environmentControllerTestUtils.ExecuteRequest("GET", fmt.Sprintf("/api/v1/applications/%s/environments/%s/deployments?latest=true", anyAppName, anyEnvironment)) @@ -1081,7 +1082,7 @@ func TestGetEnvironmentSummary_ApplicationWithNoDeployments_SecretPending(t *tes envName1, envName2 := "dev", "master" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. NewRadixApplicationBuilder(). WithRadixRegistration(operatorutils.ARadixRegistration()). @@ -1108,7 +1109,7 @@ func TestGetEnvironmentSummary_RemoveSecretFromConfig_OrphanedSecret(t *testing. orphanedEnvironment := "feature-1" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1158,7 +1159,7 @@ func TestGetEnvironmentSummary_OrphanedSecretWithDash_OrphanedSecretIsListedOk(t orphanedEnvironment := "feature-1" // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) rr, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1199,7 +1200,7 @@ func TestGetEnvironmentSummary_OrphanedSecretWithDash_OrphanedSecretIsListedOk(t func TestGetSecret_ExistingSecretInConfig_ReturnsAPendingSecret(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. ARadixApplication(). WithAppName(anyAppName). @@ -1221,7 +1222,7 @@ func TestGetSecret_ExistingSecretInConfig_ReturnsAPendingSecret(t *testing.T) { func TestCreateSecret(t *testing.T) { // Setup - commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyApplication(operatorutils. ARadixApplication(). WithAppName(anyAppName)) @@ -1234,7 +1235,7 @@ func TestCreateSecret(t *testing.T) { } func Test_GetEnvironmentEvents_Handler(t *testing.T) { - commonTestUtils, _, _, kubeclient, radixclient, _, secretproviderclient := setupTest(nil) + commonTestUtils, _, _, kubeclient, radixclient, _, secretproviderclient := setupTest(t, nil) ctrl := gomock.NewController(t) defer ctrl.Finish() eventHandler := eventMock.NewMockEventHandler(ctrl) @@ -1258,7 +1259,7 @@ func TestRestartAuxiliaryResource(t *testing.T) { auxType := "oauth" // Setup - commonTestUtils, environmentControllerTestUtils, _, kubeClient, _, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, kubeClient, _, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1304,7 +1305,7 @@ func Test_GetJobs(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1379,7 +1380,7 @@ func Test_GetJobs_Status(t *testing.T) { // Setup ctrl := gomock.NewController(t) jobSchedulerFactoryMock := mock.NewMockHandlerFactoryInterface(ctrl) - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest([]EnvironmentHandlerOptions{WithJobSchedulerHandlerFactory(jobSchedulerFactoryMock)}) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, []EnvironmentHandlerOptions{WithJobSchedulerHandlerFactory(jobSchedulerFactoryMock)}) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1455,7 +1456,7 @@ func Test_GetJobs_Status_StopIsTrue(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1530,7 +1531,7 @@ func Test_GetJob(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1628,7 +1629,7 @@ func Test_GetJob_AllProps(t *testing.T) { defaultBackoffLimit := numbers.Int32Ptr(3) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1750,7 +1751,7 @@ func Test_GetJobPayload(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, kubeClient, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, kubeClient, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1836,7 +1837,7 @@ func Test_GetBatch_JobList(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1911,7 +1912,7 @@ func Test_GetBatch_JobList_StopFlag(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -1986,7 +1987,7 @@ func Test_GetBatches_Status(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -2093,7 +2094,7 @@ func Test_GetBatches_JobListShouldBeEmpty(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(anyAppName, anyEnvironment) // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -2164,7 +2165,7 @@ func Test_StopJob(t *testing.T) { } // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -2274,7 +2275,7 @@ func Test_DeleteJob(t *testing.T) { } // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -2392,7 +2393,7 @@ func Test_StopBatch(t *testing.T) { } // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) @@ -2496,7 +2497,7 @@ func Test_DeleteBatch(t *testing.T) { } // Setup - commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(nil) + commonTestUtils, environmentControllerTestUtils, _, _, radixClient, _, _ := setupTest(t, nil) _, err := commonTestUtils.ApplyRegistration(operatorutils. NewRegistrationBuilder(). WithName(anyAppName)) diff --git a/api/environments/environment_handler.go b/api/environments/environment_handler.go index 02f504ab..9be72e82 100644 --- a/api/environments/environment_handler.go +++ b/api/environments/environment_handler.go @@ -14,13 +14,13 @@ import ( "github.com/equinor/radix-api/api/kubequery" apimodels "github.com/equinor/radix-api/api/models" "github.com/equinor/radix-api/api/pods" + "github.com/equinor/radix-api/api/utils" "github.com/equinor/radix-api/api/utils/jobscheduler" "github.com/equinor/radix-api/api/utils/predicate" "github.com/equinor/radix-api/api/utils/tlsvalidator" "github.com/equinor/radix-api/models" radixutils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" - configUtils "github.com/equinor/radix-operator/pkg/apis/applicationconfig" deployUtils "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -107,7 +107,7 @@ var validaStatusesToScaleComponent []string // Init Constructor. // Use the WithAccounts configuration function to configure a 'ready to use' EnvironmentHandler. -// EnvironmentHandlerOptions are processed in the seqeunce they are passed to this function. +// EnvironmentHandlerOptions are processed in the sequence they are passed to this function. func Init(opts ...EnvironmentHandlerOptions) EnvironmentHandler { validaStatusesToScaleComponent = []string{deploymentModels.ConsistentComponent.String(), deploymentModels.StoppedComponent.String()} @@ -446,7 +446,7 @@ func (eh EnvironmentHandler) getRadixCommonComponentUpdater(ctx context.Context, baseUpdater.componentToPatch = componentToPatch ra, _ := eh.getRadixApplicationInAppNamespace(ctx, appName) - baseUpdater.environmentConfig = configUtils.GetComponentEnvironmentConfig(ra, envName, componentName) + baseUpdater.environmentConfig = utils.GetComponentEnvironmentConfig(ra, envName, componentName) baseUpdater.componentState, err = deployments.GetComponentStateFromSpec(ctx, eh.client, appName, deploymentSummary, rd.Status, baseUpdater.environmentConfig, componentToPatch) if err != nil { return nil, err @@ -461,8 +461,7 @@ func (eh EnvironmentHandler) commit(ctx context.Context, updater radixDeployComm return err } - err = commitFunc(updater) - if err != nil { + if err := commitFunc(updater); err != nil { return err } newJSON, err := json.Marshal(rd) diff --git a/api/environmentvariables/env_vars_controller_test.go b/api/environmentvariables/env_vars_controller_test.go index d7599fe0..89fea9bd 100644 --- a/api/environmentvariables/env_vars_controller_test.go +++ b/api/environmentvariables/env_vars_controller_test.go @@ -32,8 +32,8 @@ const ( subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" ) -func setupTestWithMockHandler(mockCtrl *gomock.Controller) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, *MockEnvVarsHandler) { - kubeclient, radixclient, prometheusclient, commonTestUtils, _, secretproviderclient := setupTest() +func setupTestWithMockHandler(t *testing.T, mockCtrl *gomock.Controller) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, *MockEnvVarsHandler) { + kubeclient, radixclient, prometheusclient, commonTestUtils, _, secretproviderclient := setupTest(t) handler := NewMockEnvVarsHandler(mockCtrl) handlerFactory := NewMockenvVarsHandlerFactory(mockCtrl) @@ -45,7 +45,7 @@ func setupTestWithMockHandler(mockCtrl *gomock.Controller) (*commontest.Utils, * return &commonTestUtils, &controllerTestUtils, kubeclient, radixclient, prometheusclient, handler } -func setupTest() (*kubefake.Clientset, *fake.Clientset, *prometheusfake.Clientset, commontest.Utils, *kube.Kube, secretsstorevclient.Interface) { +func setupTest(t *testing.T) (*kubefake.Clientset, *fake.Clientset, *prometheusfake.Clientset, commontest.Utils, *kube.Kube, secretsstorevclient.Interface) { // Setup kubeclient := kubefake.NewSimpleClientset() radixclient := fake.NewSimpleClientset() @@ -54,7 +54,8 @@ func setupTest() (*kubefake.Clientset, *fake.Clientset, *prometheusfake.Clientse // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) return kubeclient, radixclient, prometheusclient, commonTestUtils, commonTestUtils.GetKubeUtil(), secretproviderclient } @@ -65,7 +66,7 @@ func Test_GetComponentEnvVars(t *testing.T) { url := fmt.Sprintf("/api/v1/applications/%s/environments/%s/components/%s/envvars", appName, environmentName, componentName) t.Run("Return env-vars", func(t *testing.T) { - commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(mockCtrl) + commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(t, mockCtrl) _, err := setupDeployment(commonTestUtils, appName, environmentName, componentName, nil) require.NoError(t, err) handler.EXPECT().GetComponentEnvVars(appName, environmentName, componentName). @@ -108,7 +109,7 @@ func Test_GetComponentEnvVars(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(mockCtrl) + commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(t, mockCtrl) _, err := setupDeployment(commonTestUtils, appName, environmentName, componentName, nil) require.NoError(t, err) handler.EXPECT().GetComponentEnvVars(appName, environmentName, componentName). @@ -129,7 +130,7 @@ func Test_GetComponentEnvVars(t *testing.T) { } func Test_ChangeEnvVar(t *testing.T) { - // setupTestWithMockHandler() + // setupTestWithMockHandler(t, ) ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -149,7 +150,7 @@ func Test_ChangeEnvVar(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(mockCtrl) + commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(t, mockCtrl) _, err := setupDeployment(commonTestUtils, appName, environmentName, componentName, nil) require.NoError(t, err) @@ -167,7 +168,7 @@ func Test_ChangeEnvVar(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(mockCtrl) + commonTestUtils, controllerTestUtils, _, _, _, handler := setupTestWithMockHandler(t, mockCtrl) _, err := setupDeployment(commonTestUtils, appName, environmentName, componentName, nil) require.NoError(t, err) diff --git a/api/environmentvariables/env_vars_handler_test.go b/api/environmentvariables/env_vars_handler_test.go index dbf02129..c4305aed 100644 --- a/api/environmentvariables/env_vars_handler_test.go +++ b/api/environmentvariables/env_vars_handler_test.go @@ -15,7 +15,7 @@ func Test_GetEnvVars(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(appName, environmentName) t.Run("Get existing env vars", func(t *testing.T) { t.Parallel() - _, _, _, commonTestUtils, kubeUtil, _ := setupTest() + _, _, _, commonTestUtils, kubeUtil, _ := setupTest(t) envVarsMap := map[string]string{ "VAR1": "val1", @@ -54,7 +54,7 @@ func Test_ChangeGetEnvVars(t *testing.T) { namespace := operatorutils.GetEnvironmentNamespace(appName, environmentName) t.Run("Change existing env var", func(t *testing.T) { t.Parallel() - _, _, _, commonTestUtils, kubeUtil, _ := setupTest() + _, _, _, commonTestUtils, kubeUtil, _ := setupTest(t) envVarsMap := map[string]string{ "VAR1": "val1", @@ -104,7 +104,7 @@ func Test_ChangeGetEnvVars(t *testing.T) { }) t.Run("Skipped changing not-existing env vars", func(t *testing.T) { t.Parallel() - _, _, _, commonTestUtils, kubeUtil, _ := setupTest() + _, _, _, commonTestUtils, kubeUtil, _ := setupTest(t) envVarsMap := map[string]string{ "VAR1": "val1", diff --git a/api/kubequery/radixdnsalias.go b/api/kubequery/radixdnsalias.go new file mode 100644 index 00000000..40794c2c --- /dev/null +++ b/api/kubequery/radixdnsalias.go @@ -0,0 +1,19 @@ +package kubequery + +import ( + "context" + + "github.com/equinor/radix-api/api/utils/labelselector" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GetRadixDNSAliases returns all RadixDNSAliases for the specified application. +func GetRadixDNSAliases(ctx context.Context, client radixclient.Interface, appName string) ([]radixv1.RadixDNSAlias, error) { + res, err := client.RadixV1().RadixDNSAliases().List(ctx, metav1.ListOptions{LabelSelector: labelselector.ForApplication(appName).String()}) + if err != nil { + return nil, err + } + return res.Items, nil +} diff --git a/api/kubequery/radixdnsalias_test.go b/api/kubequery/radixdnsalias_test.go new file mode 100644 index 00000000..0d5f3e01 --- /dev/null +++ b/api/kubequery/radixdnsalias_test.go @@ -0,0 +1,24 @@ +package kubequery + +import ( + "context" + "testing" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_GetRadixDNSAliases(t *testing.T) { + matched1 := radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: "matched1", Labels: labels.ForApplicationName("app1")}} + matched2 := radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: "matched2", Labels: labels.ForApplicationName("app1")}} + unmatched1 := radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: "unmatched1", Labels: labels.ForApplicationName("app2")}} + client := radixfake.NewSimpleClientset(&matched1, &matched2, &unmatched1) + expected := []radixv1.RadixDNSAlias{matched1, matched2} + actual, err := GetRadixDNSAliases(context.Background(), client, "app1") + require.NoError(t, err) + assert.ElementsMatch(t, expected, actual) +} diff --git a/api/models/application.go b/api/models/application.go index d805e83a..01c43136 100644 --- a/api/models/application.go +++ b/api/models/application.go @@ -2,27 +2,22 @@ package models import ( applicationModels "github.com/equinor/radix-api/api/applications/models" - environmentModels "github.com/equinor/radix-api/api/environments/models" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" networkingv1 "k8s.io/api/networking/v1" ) // BuildApplication builds an Application model. -func BuildApplication(rr *radixv1.RadixRegistration, ra *radixv1.RadixApplication, reList []radixv1.RadixEnvironment, rdList []radixv1.RadixDeployment, rjList []radixv1.RadixJob, ingressList []networkingv1.Ingress, userIsAdmin bool) *applicationModels.Application { - var environments []*environmentModels.EnvironmentSummary - if ra != nil { - environments = BuildEnvironmentSummaryList(rr, ra, reList, rdList, rjList) - } - registration := BuildApplicationRegistration(rr) - jobs := BuildJobSummaryList(rjList) - appAlias := BuildApplicationAlias(ingressList, reList) - - return &applicationModels.Application{ +func BuildApplication(rr *radixv1.RadixRegistration, ra *radixv1.RadixApplication, reList []radixv1.RadixEnvironment, rdList []radixv1.RadixDeployment, rjList []radixv1.RadixJob, ingressList []networkingv1.Ingress, userIsAdmin bool, radixDNSAliasList []radixv1.RadixDNSAlias, radixDNSZone string) *applicationModels.Application { + application := applicationModels.Application{ Name: rr.Name, - Registration: *registration, - Jobs: jobs, - Environments: environments, - AppAlias: appAlias, + Registration: *BuildApplicationRegistration(rr), + Jobs: BuildJobSummaryList(rjList), + AppAlias: BuildApplicationAlias(ingressList, reList), UserIsAdmin: userIsAdmin, } + if ra != nil { + application.Environments = BuildEnvironmentSummaryList(rr, ra, reList, rdList, rjList) + application.DNSAliases = BuildDNSAlias(ra, radixDNSAliasList, radixDNSZone) + } + return &application } diff --git a/api/models/component.go b/api/models/component.go index cea2ca95..8510ea1f 100644 --- a/api/models/component.go +++ b/api/models/component.go @@ -4,10 +4,10 @@ import ( "strings" deploymentModels "github.com/equinor/radix-api/api/deployments/models" + "github.com/equinor/radix-api/api/utils" "github.com/equinor/radix-api/api/utils/predicate" commonutils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" - operatorapplicationconfig "github.com/equinor/radix-operator/pkg/apis/applicationconfig" operatordefaults "github.com/equinor/radix-operator/pkg/apis/defaults" operatordeployment "github.com/equinor/radix-operator/pkg/apis/deployment" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -70,7 +70,7 @@ func buildComponent(radixComponent radixv1.RadixCommonDeployComponent, ra *radix } func getComponentStatus(component radixv1.RadixCommonDeployComponent, ra *radixv1.RadixApplication, rd *radixv1.RadixDeployment, pods []corev1.Pod) deploymentModels.ComponentStatus { - environmentConfig := operatorapplicationconfig.GetComponentEnvironmentConfig(ra, rd.Spec.Environment, component.GetName()) + environmentConfig := utils.GetComponentEnvironmentConfig(ra, rd.Spec.Environment, component.GetName()) if component.GetType() == radixv1.RadixComponentTypeComponent { if runningReplicaDiffersFromConfig(environmentConfig, pods) && !runningReplicaDiffersFromSpec(component, pods) && diff --git a/api/models/dns_alias.go b/api/models/dns_alias.go new file mode 100644 index 00000000..3fb274af --- /dev/null +++ b/api/models/dns_alias.go @@ -0,0 +1,33 @@ +package models + +import ( + "fmt" + + applicationModels "github.com/equinor/radix-api/api/applications/models" + "github.com/equinor/radix-common/utils/slice" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" +) + +// BuildDNSAlias builds an DNSAliases model for the application +func BuildDNSAlias(ra *radixv1.RadixApplication, radixDNSAliasList []radixv1.RadixDNSAlias, radixDNSZone string) []applicationModels.DNSAlias { + var dnsAliases []applicationModels.DNSAlias + radixDNSAliasMap := slice.Reduce(radixDNSAliasList, make(map[string]*radixv1.RadixDNSAlias), func(acc map[string]*radixv1.RadixDNSAlias, radixDNSAlias radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { + acc[radixDNSAlias.GetName()] = &radixDNSAlias + return acc + }) + for _, dnsAlias := range ra.Spec.DNSAlias { + aliasModel := applicationModels.DNSAlias{ + URL: fmt.Sprintf("%s.%s", dnsAlias.Alias, radixDNSZone), + ComponentName: dnsAlias.Component, + EnvironmentName: dnsAlias.Environment, + } + if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Alias]; ok { + aliasModel.Status = applicationModels.DNSAliasStatus{ + Condition: string(radixDNSAlias.Status.Condition), + Message: radixDNSAlias.Status.Message, + } + } + dnsAliases = append(dnsAliases, aliasModel) + } + return dnsAliases +} diff --git a/api/models/secret.go b/api/models/secret.go index f5074128..929a4870 100644 --- a/api/models/secret.go +++ b/api/models/secret.go @@ -11,6 +11,7 @@ import ( "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" operatordeployment "github.com/equinor/radix-operator/pkg/apis/deployment" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" operatorutils "github.com/equinor/radix-operator/pkg/apis/utils" @@ -64,7 +65,7 @@ func getSecretsForDeployment(secretList []corev1.Secret, rd *radixv1.RadixDeploy var secretDTOsMap []secretModels.Secret for componentName, secretNamesMap := range componentSecretsMap { secretObjectName := operatorutils.GetComponentSecretName(componentName) - secret, ok := slice.FindFirst(secretList, isSecretWithName(secretObjectName)) + secr, ok := slice.FindFirst(secretList, isSecretWithName(secretObjectName)) if !ok { // Mark secrets as Pending (exist in config, does not exist in cluster) due to no secret object in the cluster for secretName := range secretNamesMap { @@ -79,7 +80,7 @@ func getSecretsForDeployment(secretList []corev1.Secret, rd *radixv1.RadixDeploy continue } - clusterSecretEntriesMap := secret.Data + clusterSecretEntriesMap := secr.Data for secretName := range secretNamesMap { status := secretModels.Consistent.String() if _, exists := clusterSecretEntriesMap[secretName]; !exists { @@ -292,12 +293,12 @@ func getSecretsForComponentAuthentication(secretList []corev1.Secret, component func getSecretsForComponentAuthenticationClientCertificate(secretList []corev1.Secret, component radixv1.RadixCommonDeployComponent) []secretModels.Secret { var secrets []secretModels.Secret - if auth := component.GetAuthentication(); auth != nil && component.IsPublic() && operatordeployment.IsSecretRequiredForClientCertificate(auth.ClientCertificate) { + if auth := component.GetAuthentication(); auth != nil && component.IsPublic() && ingress.IsSecretRequiredForClientCertificate(auth.ClientCertificate) { secretName := operatorutils.GetComponentClientCertificateSecretName(component.GetName()) secretStatus := secretModels.Consistent.String() - if secret, ok := slice.FindFirst(secretList, isSecretWithName(secretName)); ok { - secretValue := strings.TrimSpace(string(secret.Data["ca.crt"])) + if secr, ok := slice.FindFirst(secretList, isSecretWithName(secretName)); ok { + secretValue := strings.TrimSpace(string(secr.Data["ca.crt"])) if strings.EqualFold(secretValue, secretDefaultData) { secretStatus = secretModels.Pending.String() } @@ -330,14 +331,14 @@ func getSecretsForComponentAuthenticationOAuth2(secretList []corev1.Secret, comp redisPasswordStatus := secretModels.Consistent.String() secretName := operatorutils.GetAuxiliaryComponentSecretName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix) - if secret, ok := slice.FindFirst(secretList, isSecretWithName(secretName)); ok { - if secretValue, found := secret.Data[defaults.OAuthClientSecretKeyName]; !found || len(strings.TrimSpace(string(secretValue))) == 0 { + if secr, ok := slice.FindFirst(secretList, isSecretWithName(secretName)); ok { + if secretValue, found := secr.Data[defaults.OAuthClientSecretKeyName]; !found || len(strings.TrimSpace(string(secretValue))) == 0 { clientSecretStatus = secretModels.Pending.String() } - if secretValue, found := secret.Data[defaults.OAuthCookieSecretKeyName]; !found || len(strings.TrimSpace(string(secretValue))) == 0 { + if secretValue, found := secr.Data[defaults.OAuthCookieSecretKeyName]; !found || len(strings.TrimSpace(string(secretValue))) == 0 { cookieSecretStatus = secretModels.Pending.String() } - if secretValue, found := secret.Data[defaults.OAuthRedisPasswordKeyName]; !found || len(strings.TrimSpace(string(secretValue))) == 0 { + if secretValue, found := secr.Data[defaults.OAuthRedisPasswordKeyName]; !found || len(strings.TrimSpace(string(secretValue))) == 0 { redisPasswordStatus = secretModels.Pending.String() } } else { diff --git a/api/privateimagehubs/internal/secrets.go b/api/privateimagehubs/internal/secrets.go new file mode 100644 index 00000000..f892455c --- /dev/null +++ b/api/privateimagehubs/internal/secrets.go @@ -0,0 +1,59 @@ +package internal + +import ( + "fmt" + + "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/kube" + operatorutils "github.com/equinor/radix-operator/pkg/apis/utils" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" +) + +// UpdatePrivateImageHubsSecretsPassword update secret password +func UpdatePrivateImageHubsSecretsPassword(kubeUtil *kube.Kube, appName, server, password string) error { + namespace := operatorutils.GetAppNamespace(appName) + secret, _ := kubeUtil.GetSecret(namespace, defaults.PrivateImageHubSecretName) + if secret == nil { + return fmt.Errorf("private image hub secret does not exist for app %s", appName) + } + + imageHubs, err := applicationconfig.GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) + if err != nil { + return err + } + + if config, ok := imageHubs[server]; ok { + config.Password = password + imageHubs[server] = config + secretValue, err := applicationconfig.GetImageHubsSecretValue(imageHubs) + if err != nil { + return err + } + return applicationconfig.ApplyPrivateImageHubSecret(kubeUtil, namespace, appName, secretValue) + } + return fmt.Errorf("private image hub secret does not contain config for server %s", server) +} + +// GetPendingPrivateImageHubSecrets returns a list of private image hubs where secret value is not set +func GetPendingPrivateImageHubSecrets(kubeUtil *kube.Kube, appName string) ([]string, error) { + pendingSecrets := []string{} + ns := operatorutils.GetAppNamespace(appName) + secret, err := kubeUtil.GetSecret(ns, defaults.PrivateImageHubSecretName) + if err != nil && !errors.IsNotFound(err) { + return nil, err + } + + imageHubs, err := applicationconfig.GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) + if err != nil { + return nil, err + } + + for key, imageHub := range imageHubs { + if imageHub.Password == "" { + pendingSecrets = append(pendingSecrets, key) + } + } + return pendingSecrets, nil +} diff --git a/api/privateimagehubs/privateimagehubs_controller.go b/api/privateimagehubs/privateimagehubs_controller.go index f3b90101..d3142356 100644 --- a/api/privateimagehubs/privateimagehubs_controller.go +++ b/api/privateimagehubs/privateimagehubs_controller.go @@ -140,7 +140,7 @@ func (dc *privateImageHubController) ChangePrivateImageHubSecret(accounts models } privateImageHubHandler := Init(accounts) - err := privateImageHubHandler.UpdatePrivateImageHubValue(r.Context(), appName, serverName, secretParameters.SecretValue) + err := privateImageHubHandler.UpdatePrivateImageHubValue(appName, serverName, secretParameters.SecretValue) if err != nil { radixhttp.ErrorResponse(w, r, err) diff --git a/api/privateimagehubs/privateimagehubs_handler.go b/api/privateimagehubs/privateimagehubs_handler.go index 66116ed3..2ea25ae3 100644 --- a/api/privateimagehubs/privateimagehubs_handler.go +++ b/api/privateimagehubs/privateimagehubs_handler.go @@ -3,23 +3,27 @@ package privateimagehubs import ( "context" + "github.com/equinor/radix-api/api/privateimagehubs/internal" "github.com/equinor/radix-api/api/privateimagehubs/models" "github.com/equinor/radix-api/api/utils" sharedModels "github.com/equinor/radix-api/models" + "github.com/equinor/radix-operator/pkg/apis/kube" ) // PrivateImageHubHandler Instance variables type PrivateImageHubHandler struct { userAccount sharedModels.Account serviceAccount sharedModels.Account + kubeUtil *kube.Kube } // Init Constructor func Init(accounts sharedModels.Accounts) PrivateImageHubHandler { - + kubeUtil, _ := kube.New(accounts.UserAccount.Client, accounts.UserAccount.RadixClient, accounts.UserAccount.SecretProviderClient) return PrivateImageHubHandler{ userAccount: accounts.UserAccount, serviceAccount: accounts.ServiceAccount, + kubeUtil: kubeUtil, } } @@ -30,7 +34,7 @@ func (ph PrivateImageHubHandler) GetPrivateImageHubs(ctx context.Context, appNam if err != nil { return []models.ImageHubSecret{}, nil } - pendingImageHubSecrets, err := application.GetPendingPrivateImageHubSecrets() + pendingImageHubSecrets, err := internal.GetPendingPrivateImageHubSecrets(ph.kubeUtil, appName) if err != nil { return nil, err } @@ -49,12 +53,8 @@ func (ph PrivateImageHubHandler) GetPrivateImageHubs(ctx context.Context, appNam } // UpdatePrivateImageHubValue updates the private image hub value with new password -func (ph PrivateImageHubHandler) UpdatePrivateImageHubValue(ctx context.Context, appName, server, password string) error { - application, err := utils.CreateApplicationConfig(ctx, &ph.userAccount, appName) - if err != nil { - return err - } - return application.UpdatePrivateImageHubsSecretsPassword(server, password) +func (ph PrivateImageHubHandler) UpdatePrivateImageHubValue(appName, server, password string) error { + return internal.UpdatePrivateImageHubsSecretsPassword(ph.kubeUtil, appName, server, password) } func getImageHubSecretStatus(pendingImageHubSecrets []string, server string) models.ImageHubSecretStatus { diff --git a/api/privateimagehubs/privateimagehubs_handler_test.go b/api/privateimagehubs/privateimagehubs_handler_test.go new file mode 100644 index 00000000..882b4af3 --- /dev/null +++ b/api/privateimagehubs/privateimagehubs_handler_test.go @@ -0,0 +1,127 @@ +package privateimagehubs_test + +import ( + "context" + "testing" + + "github.com/equinor/radix-api/api/privateimagehubs/internal" + "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/test" + "github.com/equinor/radix-operator/pkg/apis/utils" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + kubefake "k8s.io/client-go/kubernetes/fake" + secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" +) + +const ( + clusterName = "AnyClusterName" +) + +func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { + client, _, kubeUtil, err := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{}) + require.NoError(t, err) + pendingSecrets, _ := internal.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") + + secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) + + assert.NotNil(t, secret) + assert.Equal(t, + "{\"auths\":{}}", + string(secret.Data[corev1.DockerConfigJsonKey])) + assert.Equal(t, 0, len(pendingSecrets)) + assert.Error(t, internal.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password")) +} + +func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { + client, _, kubeUtil, err := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ + Username: "814607e6-3d71-44a7-8476-50e8b281abbc", + Email: "radix@equinor.com", + }, + }) + require.NoError(t, err) + pendingSecrets, _ := internal.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") + + assert.Equal(t, "privaterepodeleteme.azurecr.io", pendingSecrets[0]) + + if err := internal.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password"); err != nil { + require.NoError(t, err) + } + secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) + pendingSecrets, _ = internal.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") + + assert.Equal(t, + "{\"auths\":{\"privaterepodeleteme.azurecr.io\":{\"username\":\"814607e6-3d71-44a7-8476-50e8b281abbc\",\"password\":\"a-password\",\"email\":\"radix@equinor.com\",\"auth\":\"ODE0NjA3ZTYtM2Q3MS00NGE3LTg0NzYtNTBlOGIyODFhYmJjOmEtcGFzc3dvcmQ=\"}}}", + string(secret.Data[corev1.DockerConfigJsonKey])) + assert.Equal(t, 0, len(pendingSecrets)) +} + +func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *applicationconfig.ApplicationConfig, *kube.Kube, error) { + tu, client, kubeUtil, radixClient, err := setupTest() + if err != nil { + return nil, nil, nil, err + } + appBuilder := utils.ARadixApplication(). + WithAppName("any-app"). + WithEnvironment("dev", "master") + for key, config := range privateImageHubs { + appBuilder.WithPrivateImageRegistry(key, config.Username, config.Email) + } + + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, appBuilder); err != nil { + return nil, nil, nil, err + } + appConfig := getAppConfig(client, kubeUtil, radixClient, appBuilder) + return client, appConfig, kubeUtil, nil +} + +func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Interface, error) { + kubeClient := kubefake.NewSimpleClientset() + radixClient := radixfake.NewSimpleClientset() + secretproviderclient := secretproviderfake.NewSimpleClientset() + kubeUtil, _ := kube.New(kubeClient, radixClient, secretproviderclient) + handlerTestUtils := test.NewTestUtils(kubeClient, radixClient, secretproviderclient) + if err := handlerTestUtils.CreateClusterPrerequisites(clusterName, "0.0.0.0", "anysubid"); err != nil { + return nil, nil, nil, nil, err + } + return &handlerTestUtils, kubeClient, kubeUtil, radixClient, nil +} + +func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeUtil *kube.Kube, + radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) error { + + ra, err := tu.ApplyApplication(applicationBuilder) + if err != nil { + return err + } + + radixRegistration, err := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil) + + err = applicationConfig.OnSync() + if err != nil { + return err + } + + return nil +} + +func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) *applicationconfig.ApplicationConfig { + ra := applicationBuilder.BuildRA() + radixRegistration, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) + + return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil) +} diff --git a/api/router/server.go b/api/router/server.go index 9e19cb1b..094da3c6 100644 --- a/api/router/server.go +++ b/api/router/server.go @@ -5,6 +5,7 @@ import ( "net/http" "os" + "github.com/equinor/radix-api/api/defaults" "github.com/equinor/radix-api/api/utils" "github.com/equinor/radix-api/models" "github.com/equinor/radix-api/swaggerui" @@ -36,16 +37,11 @@ func NewServer(clusterName string, kubeUtil utils.KubeUtil, controllers ...model negroni.Wrap(router), )) - serveMux.Handle(fmt.Sprintf("%s/", admissionControllerRootPath), negroni.New( - negroni.Wrap(router), - )) - serveMux.Handle("/api/", negroni.New( negroni.Wrap(router), )) - // TODO: We should maybe have oauth to stop any non-radix user from beeing - // able to see the API + // TODO: We should maybe have oauth to stop any non-radix user from being able to see the API serveMux.Handle("/swaggerui/", negroni.New( negroni.Wrap(router), )) @@ -66,7 +62,7 @@ func NewServer(clusterName string, kubeUtil utils.KubeUtil, controllers ...model } func getCORSHandler(clusterName string, handler http.Handler, useOutClusterClient bool) http.Handler { - radixDNSZone := os.Getenv(radixDNSZoneEnvironmentVariable) + radixDNSZone := os.Getenv(defaults.RadixDNSZoneEnvironmentVariable) corsOptions := cors.Options{ AllowedOrigins: []string{ diff --git a/api/secrets/secret_controller_test.go b/api/secrets/secret_controller_test.go index bc9c6031..13cd2f9c 100644 --- a/api/secrets/secret_controller_test.go +++ b/api/secrets/secret_controller_test.go @@ -37,7 +37,7 @@ const ( subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c" ) -func setupTest() (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { +func setupTest(t *testing.T) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { // Setup kubeclient := kubefake.NewSimpleClientset() radixclient := fake.NewSimpleClientset() @@ -46,7 +46,8 @@ func setupTest() (*commontest.Utils, *controllertest.Utils, kubernetes.Interface // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) // secretControllerTestUtils is used for issuing HTTP request and processing responses secretControllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewSecretController()) @@ -54,8 +55,8 @@ func setupTest() (*commontest.Utils, *controllertest.Utils, kubernetes.Interface return &commonTestUtils, &secretControllerTestUtils, kubeclient, radixclient, prometheusclient, secretproviderclient } -func executeUpdateComponentSecretTest(oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue string) (*httptest.ResponseRecorder, error) { - return executeUpdateSecretTest( +func executeUpdateComponentSecretTest(t *testing.T, oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue string) (*httptest.ResponseRecorder, error) { + return executeUpdateSecretTest(t, oldSecretValue, updateSecret, updateComponent, @@ -64,14 +65,8 @@ func executeUpdateComponentSecretTest(oldSecretValue, updateSecret, updateCompon configureApplicationComponentSecret) } -func executeUpdateJobSecretTest(oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue string) (*httptest.ResponseRecorder, error) { - return executeUpdateSecretTest( - oldSecretValue, - updateSecret, - updateComponent, - updateSecretName, - updateSecretValue, - configureApplicationJobSecret) +func executeUpdateJobSecretTest(t *testing.T, oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue string) (*httptest.ResponseRecorder, error) { + return executeUpdateSecretTest(t, oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue, configureApplicationJobSecret) } func configureApplicationComponentSecret(builder *operatorutils.ApplicationBuilder) { @@ -90,14 +85,14 @@ func configureApplicationJobSecret(builder *operatorutils.ApplicationBuilder) { ) } -func executeUpdateSecretTest(oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue string, appConfigurator func(builder *operatorutils.ApplicationBuilder)) (*httptest.ResponseRecorder, error) { +func executeUpdateSecretTest(t *testing.T, oldSecretValue, updateSecret, updateComponent, updateSecretName, updateSecretValue string, appConfigurator func(builder *operatorutils.ApplicationBuilder)) (*httptest.ResponseRecorder, error) { // Setup parameters := secretModels.SecretParameters{ SecretValue: updateSecretValue, } - commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest() + commonTestUtils, controllerTestUtils, kubeclient, _, _, _ := setupTest(t) appBuilder := operatorutils. ARadixApplication(). WithAppName(anyAppName) @@ -155,11 +150,11 @@ func TestUpdateSecret_OK(t *testing.T) { oldSecretValue := "oldvalue" updateSecretValue := "newvalue" - response, err := executeUpdateComponentSecretTest(oldSecretValue, anyEnvironment, anyComponentName, anyEnvironmentName, updateSecretValue) + response, err := executeUpdateComponentSecretTest(t, oldSecretValue, anyEnvironment, anyComponentName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) assert.Equal(t, http.StatusOK, response.Code) - response, err = executeUpdateJobSecretTest(oldSecretValue, anyEnvironment, anyJobName, anyEnvironmentName, updateSecretValue) + response, err = executeUpdateJobSecretTest(t, oldSecretValue, anyEnvironment, anyJobName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) assert.Equal(t, http.StatusOK, response.Code) } @@ -169,11 +164,11 @@ func TestUpdateSecret_NonExistingEnvironment_Missing2(t *testing.T) { oldSecretValue := "oldvalue" updateSecretValue := "newvalue" - response, err := executeUpdateComponentSecretTest(oldSecretValue, anyEnvironment, anyComponentName, nonExistingSecretName, updateSecretValue) + response, err := executeUpdateComponentSecretTest(t, oldSecretValue, anyEnvironment, anyComponentName, nonExistingSecretName, updateSecretValue) require.NoError(t, err) assert.Equal(t, http.StatusOK, response.Code) - response, err = executeUpdateJobSecretTest(oldSecretValue, anyEnvironment, anyJobName, nonExistingSecretName, updateSecretValue) + response, err = executeUpdateJobSecretTest(t, oldSecretValue, anyEnvironment, anyJobName, nonExistingSecretName, updateSecretValue) require.NoError(t, err) assert.Equal(t, http.StatusOK, response.Code) } @@ -182,14 +177,14 @@ func TestUpdateSecret_EmptySecretValue_ValidationError(t *testing.T) { oldSecretValue := "oldvalue" updateSecretValue := "" - response, err := executeUpdateComponentSecretTest(oldSecretValue, anyEnvironment, anyComponentName, anyEnvironmentName, updateSecretValue) + response, err := executeUpdateComponentSecretTest(t, oldSecretValue, anyEnvironment, anyComponentName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) errorResponse, _ := controllertest.GetErrorResponse(response) assert.Equal(t, http.StatusBadRequest, response.Code) assert.Equal(t, "New secret value is empty", errorResponse.Message) assert.Equal(t, "Secret failed validation", errorResponse.Err.Error()) - response, err = executeUpdateJobSecretTest(oldSecretValue, anyEnvironment, anyJobName, anyEnvironmentName, updateSecretValue) + response, err = executeUpdateJobSecretTest(t, oldSecretValue, anyEnvironment, anyJobName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) errorResponse, _ = controllertest.GetErrorResponse(response) assert.Equal(t, http.StatusBadRequest, response.Code) @@ -201,11 +196,11 @@ func TestUpdateSecret_NoUpdate_NoError(t *testing.T) { oldSecretValue := "oldvalue" updateSecretValue := "oldvalue" - response, err := executeUpdateComponentSecretTest(oldSecretValue, anyEnvironment, anyComponentName, anyEnvironmentName, updateSecretValue) + response, err := executeUpdateComponentSecretTest(t, oldSecretValue, anyEnvironment, anyComponentName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) assert.Equal(t, http.StatusOK, response.Code) - response, err = executeUpdateJobSecretTest(oldSecretValue, anyEnvironment, anyJobName, anyEnvironmentName, updateSecretValue) + response, err = executeUpdateJobSecretTest(t, oldSecretValue, anyEnvironment, anyJobName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) assert.Equal(t, http.StatusOK, response.Code) } @@ -216,13 +211,13 @@ func TestUpdateSecret_NonExistingComponent_Missing(t *testing.T) { oldSecretValue := "oldvalue" updateSecretValue := "newvalue" - response, err := executeUpdateComponentSecretTest(oldSecretValue, anyEnvironment, nonExistingComponent, anyEnvironmentName, updateSecretValue) + response, err := executeUpdateComponentSecretTest(t, oldSecretValue, anyEnvironment, nonExistingComponent, anyEnvironmentName, updateSecretValue) require.NoError(t, err) errorResponse, _ := controllertest.GetErrorResponse(response) assert.Equal(t, http.StatusNotFound, response.Code) assert.Equal(t, fmt.Sprintf("secrets \"%s\" not found", nonExistingSecretObjName), errorResponse.Err.Error()) - response, err = executeUpdateJobSecretTest(oldSecretValue, anyEnvironment, nonExistingComponent, anyEnvironmentName, updateSecretValue) + response, err = executeUpdateJobSecretTest(t, oldSecretValue, anyEnvironment, nonExistingComponent, anyEnvironmentName, updateSecretValue) require.NoError(t, err) errorResponse, _ = controllertest.GetErrorResponse(response) assert.Equal(t, http.StatusNotFound, response.Code) @@ -234,14 +229,14 @@ func TestUpdateSecret_NonExistingEnvironment_Missing(t *testing.T) { oldSecretValue := "oldvalue" updateSecretValue := "newvalue" - response, err := executeUpdateComponentSecretTest(oldSecretValue, nonExistingSecret, anyComponentName, anyEnvironmentName, updateSecretValue) + response, err := executeUpdateComponentSecretTest(t, oldSecretValue, nonExistingSecret, anyComponentName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) errorResponse, _ := controllertest.GetErrorResponse(response) secretObjName := operatorutils.GetComponentSecretName(anyComponentName) assert.Equal(t, http.StatusNotFound, response.Code) assert.Equal(t, fmt.Sprintf("secrets \"%s\" not found", secretObjName), errorResponse.Err.Error()) - response, err = executeUpdateJobSecretTest(oldSecretValue, nonExistingSecret, anyJobName, anyEnvironmentName, updateSecretValue) + response, err = executeUpdateJobSecretTest(t, oldSecretValue, nonExistingSecret, anyJobName, anyEnvironmentName, updateSecretValue) require.NoError(t, err) errorResponse, _ = controllertest.GetErrorResponse(response) secretObjName = operatorutils.GetComponentSecretName(anyJobName) diff --git a/api/utils/logs/logs.go b/api/utils/logs/logs.go index 2c8ad47d..0862b958 100644 --- a/api/utils/logs/logs.go +++ b/api/utils/logs/logs.go @@ -1,13 +1,13 @@ package logs import ( + "errors" "net/http" "strconv" "strings" "time" "github.com/equinor/radix-common/utils" - commonErrors "github.com/equinor/radix-common/utils/errors" ) // GetLogParams Gets parameters for a log output @@ -51,5 +51,5 @@ func GetLogParams(r *http.Request) (time.Time, bool, *int64, error, bool) { } logLines = &val } - return since, asFile, logLines, commonErrors.Concat(errs), previousLog + return since, asFile, logLines, errors.Join(errs...), previousLog } diff --git a/api/utils/radixapplication.go b/api/utils/radixapplication.go index effd8a43..ec2dddc9 100644 --- a/api/utils/radixapplication.go +++ b/api/utils/radixapplication.go @@ -2,7 +2,11 @@ package utils import ( "context" + "strings" + "github.com/equinor/radix-api/models" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -23,5 +27,37 @@ func CreateApplicationConfig(ctx context.Context, user *models.Account, appName } kubeUtils, _ := kube.New(user.Client, user.RadixClient, user.SecretProviderClient) - return applicationconfig.NewApplicationConfig(user.Client, kubeUtils, user.RadixClient, registration, radixApp) + return applicationconfig.NewApplicationConfig(user.Client, kubeUtils, user.RadixClient, registration, radixApp, &dnsalias.DNSConfig{}), nil +} + +// GetComponentEnvironmentConfig Gets environment config of component +func GetComponentEnvironmentConfig(ra *radixv1.RadixApplication, envName, componentName string) radixv1.RadixCommonEnvironmentConfig { + component := getRadixCommonComponentByName(ra, componentName) + if component == nil { + return nil + } + return getEnvironmentConfigByName(component, envName) +} + +func getEnvironmentConfigByName(component radixv1.RadixCommonComponent, envName string) radixv1.RadixCommonEnvironmentConfig { + for _, environment := range component.GetEnvironmentConfig() { + if strings.EqualFold(environment.GetEnvironment(), envName) { + return environment + } + } + return nil +} + +func getRadixCommonComponentByName(ra *radixv1.RadixApplication, name string) radixv1.RadixCommonComponent { + for _, component := range ra.Spec.Components { + if strings.EqualFold(component.Name, name) { + return &component + } + } + for _, jobComponent := range ra.Spec.Jobs { + if strings.EqualFold(jobComponent.Name, name) { + return &jobComponent + } + } + return nil } diff --git a/api/utils/test.go b/api/utils/test.go index 7a89b263..9e1528f3 100644 --- a/api/utils/test.go +++ b/api/utils/test.go @@ -1,9 +1,13 @@ package utils import ( + "testing" + "github.com/equinor/radix-operator/pkg/apis/application" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/deployment" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" commontest "github.com/equinor/radix-operator/pkg/apis/test" operatorutils "github.com/equinor/radix-operator/pkg/apis/utils" @@ -11,6 +15,7 @@ import ( "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" prometheusclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" + "github.com/stretchr/testify/require" "k8s.io/client-go/kubernetes" kubefake "k8s.io/client-go/kubernetes/fake" secretsstorevclient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned" @@ -23,7 +28,7 @@ const ( subscriptionId = "bd9f9eaa-2703-47c6-b5e0-faf4e058df73" ) -func SetupTest() (*commontest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { +func SetupTest(t *testing.T) (*commontest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface) { kubeClient := kubefake.NewSimpleClientset() radixClient := fake.NewSimpleClientset() prometheusClient := prometheusfake.NewSimpleClientset() @@ -31,8 +36,8 @@ func SetupTest() (*commontest.Utils, kubernetes.Interface, radixclient.Interface // commonTestUtils is used for creating CRDs commonTestUtils := commontest.NewTestUtils(kubeClient, radixClient, secretProviderClient) - commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) - + err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId) + require.NoError(t, err) return &commonTestUtils, kubeClient, radixClient, prometheusClient, secretProviderClient } @@ -46,7 +51,6 @@ func ApplyRegistrationWithSync(client kubernetes.Interface, radixclient radixcli registration, _ := application.NewApplication(client, kubeUtils, radixclient, registrationBuilder.BuildRR()) return registration.OnSync() - } // ApplyApplicationWithSync syncs based on application builder, and default builder for registration. @@ -60,16 +64,20 @@ func ApplyApplicationWithSync(client kubernetes.Interface, radixclient radixclie kubeUtils, _ := kube.New(client, radixclient, nil) _, err = commonTestUtils.ApplyApplication(applicationBuilder) + if err != nil { + panic(err) + } + _, err = commonTestUtils.ApplyApplication(applicationBuilder) if err != nil { return err } - applicationConfig, _ := applicationconfig.NewApplicationConfig(client, kubeUtils, radixclient, registrationBuilder.BuildRR(), applicationBuilder.BuildRA()) + applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtils, radixclient, registrationBuilder.BuildRR(), applicationBuilder.BuildRA(), &dnsalias.DNSConfig{DNSZone: "dev.radix.equinor.com"}) return applicationConfig.OnSync() } // ApplyDeploymentWithSync syncs based on deployment builder, and default builders for application and registration. -func ApplyDeploymentWithSync(client kubernetes.Interface, radixclient radixclient.Interface, promclient prometheusclient.Interface, commonTestUtils *commontest.Utils, secretproviderclient secretsstorevclient.Interface, deploymentBuilder operatorutils.DeploymentBuilder) error { +func ApplyDeploymentWithSync(client kubernetes.Interface, radixclient radixclient.Interface, prometheusClient prometheusclient.Interface, commonTestUtils *commontest.Utils, secretproviderclient secretsstorevclient.Interface, deploymentBuilder operatorutils.DeploymentBuilder) error { applicationBuilder := deploymentBuilder.GetApplicationBuilder() registrationBuilder := applicationBuilder.GetRegistrationBuilder() @@ -80,6 +88,6 @@ func ApplyDeploymentWithSync(client kubernetes.Interface, radixclient radixclien kubeUtils, _ := kube.New(client, radixclient, secretproviderclient) rd, _ := commonTestUtils.ApplyDeployment(deploymentBuilder) - deployment := deployment.NewDeploymentSyncer(client, kubeUtils, radixclient, promclient, registrationBuilder.BuildRR(), rd, "123456", 443, 10, []deployment.IngressAnnotationProvider{}, []deployment.AuxiliaryResourceManager{}) - return deployment.OnSync() + deploymentSyncer := deployment.NewDeploymentSyncer(client, kubeUtils, radixclient, prometheusClient, registrationBuilder.BuildRR(), rd, "123456", 443, 10, []ingress.AnnotationProvider{}, []deployment.AuxiliaryResourceManager{}) + return deploymentSyncer.OnSync() } diff --git a/go.mod b/go.mod index b5954188..9e982c9a 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/equinor/radix-api go 1.21 require ( - github.com/equinor/radix-common v1.5.0 - github.com/equinor/radix-job-scheduler v1.8.3 - github.com/equinor/radix-operator v1.43.10 + github.com/equinor/radix-common v1.7.0 + github.com/equinor/radix-job-scheduler v1.8.4 + github.com/equinor/radix-operator v1.47.0 github.com/evanphx/json-patch/v5 v5.6.0 github.com/go-swagger/go-swagger v0.30.5 github.com/golang-jwt/jwt/v4 v4.5.0 @@ -16,6 +16,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/prometheus-operator/prometheus-operator/pkg/client v0.64.1 github.com/prometheus/client_golang v1.16.0 + github.com/rakyll/statik v0.1.7 github.com/rs/cors v1.8.3 github.com/sirupsen/logrus v1.9.3 github.com/spf13/pflag v1.0.5 @@ -23,7 +24,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/tektoncd/pipeline v0.53.0 github.com/urfave/negroni/v3 v3.0.0 - golang.org/x/sync v0.4.0 + golang.org/x/sync v0.5.0 k8s.io/api v0.27.6 k8s.io/apimachinery v0.27.6 k8s.io/client-go v0.27.6 @@ -95,7 +96,7 @@ require ( golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect diff --git a/go.sum b/go.sum index 1e13a422..e4b49d78 100644 --- a/go.sum +++ b/go.sum @@ -91,12 +91,12 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/equinor/radix-common v1.5.0 h1:z5hQHlKG2x16/NnV4b9ynf9n5ZageYUewE4MANdA96Y= -github.com/equinor/radix-common v1.5.0/go.mod h1:UZ69U56VFtTxABi5JjGdaqn9Df5ilfTTqzUQ0riofVM= -github.com/equinor/radix-job-scheduler v1.8.3 h1:SqxbLD3vfwQXlxr6U6R9odeonu5uTKLoBVv9P6Tqins= -github.com/equinor/radix-job-scheduler v1.8.3/go.mod h1:r71td0yDeDixdiMtq5TuCpCICD3lMHR8d1o5rSgTrTo= -github.com/equinor/radix-operator v1.43.10 h1:EuLrUZZurXKqdWF23t/XjYDSjhjHfUVR5qPU6xLWU3E= -github.com/equinor/radix-operator v1.43.10/go.mod h1:j/Lb9bcof4L+KjtHVv5GD6MqYVsxHSGsliIP6C2F8YU= +github.com/equinor/radix-common v1.7.0 h1:DJHoBZTNzqEHw9faIWrSPGhPKEew/HBWc9MLCek6qgI= +github.com/equinor/radix-common v1.7.0/go.mod h1:9hHvudaiqmoIjCqKlsW14jMj8qU/b/wMXUwkffd9MUw= +github.com/equinor/radix-job-scheduler v1.8.4 h1:vqhP/xmOiU8UoaVhOoPjIQRSScmxSt9jMmYhEAzjIao= +github.com/equinor/radix-job-scheduler v1.8.4/go.mod h1:r71td0yDeDixdiMtq5TuCpCICD3lMHR8d1o5rSgTrTo= +github.com/equinor/radix-operator v1.47.0 h1:VjmHvp+4SPqKK/tJY0Hg4MV8nVI2IB5Jcbvg0Cbm5uQ= +github.com/equinor/radix-operator v1.47.0/go.mod h1:ygJYuO8paAlRPEvCqwAqXCRGe7WvRrzX1yAjULAH2DA= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= @@ -534,8 +534,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -583,8 +583,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/main.go b/main.go index 4e591cd5..b2e2c567 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "net/http" + _ "net/http/pprof" "os" "strconv" @@ -18,25 +19,18 @@ import ( "github.com/spf13/pflag" // Controllers - "github.com/equinor/radix-api/api/admissioncontrollers" "github.com/equinor/radix-api/api/alerting" "github.com/equinor/radix-api/api/applications" "github.com/equinor/radix-api/api/buildsecrets" + build_models "github.com/equinor/radix-api/api/buildstatus/models" "github.com/equinor/radix-api/api/deployments" "github.com/equinor/radix-api/api/environments" "github.com/equinor/radix-api/api/jobs" "github.com/equinor/radix-api/api/privateimagehubs" - - build_models "github.com/equinor/radix-api/api/buildstatus/models" - - router "github.com/equinor/radix-api/api/router" - "github.com/equinor/radix-api/models" - + "github.com/equinor/radix-api/api/router" "github.com/equinor/radix-api/api/utils" - - _ "net/http/pprof" - _ "github.com/equinor/radix-api/docs" + "github.com/equinor/radix-api/models" ) const ( @@ -107,7 +101,6 @@ func getControllers() ([]models.Controller, error) { } return []models.Controller{ - admissioncontrollers.NewAdmissionController(), applications.NewApplicationController(nil, applicationHandlerFactory), deployments.NewDeploymentController(), jobs.NewJobController(), diff --git a/swaggerui/html/swagger.json b/swaggerui/html/swagger.json index 5374a0e0..7e1928cb 100644 --- a/swaggerui/html/swagger.json +++ b/swaggerui/html/swagger.json @@ -4931,6 +4931,14 @@ "appAlias": { "$ref": "#/definitions/ApplicationAlias" }, + "dnsAliases": { + "description": "DNS aliases showing nicer endpoint for application, without \"app.\" subdomain domain", + "type": "array", + "items": { + "$ref": "#/definitions/DNSAlias" + }, + "x-go-name": "DNSAliases" + }, "environments": { "description": "Environments List of environments for this application", "type": "array", @@ -5549,6 +5557,54 @@ }, "x-go-package": "github.com/equinor/radix-api/api/deployments/models" }, + "DNSAlias": { + "description": "DNSAlias holds public DNS alias information", + "type": "object", + "required": [ + "url", + "componentName", + "environmentName" + ], + "properties": { + "componentName": { + "description": "ComponentName the component exposing the endpoint", + "type": "string", + "x-go-name": "ComponentName", + "example": "frontend" + }, + "environmentName": { + "description": "EnvironmentName the environment hosting the endpoint", + "type": "string", + "x-go-name": "EnvironmentName", + "example": "prod" + }, + "status": { + "$ref": "#/definitions/DNSAliasStatus" + }, + "url": { + "description": "URL the public endpoint", + "type": "string", + "x-go-name": "URL", + "example": "https://my-app.radix.equinor.com" + } + }, + "x-go-package": "github.com/equinor/radix-api/api/applications/models" + }, + "DNSAliasStatus": { + "description": "DNSAliasStatus Status of the DNSAlias", + "type": "object", + "properties": { + "condition": { + "type": "string", + "x-go-name": "Condition" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "x-go-package": "github.com/equinor/radix-api/api/applications/models" + }, "DeployKeyAndSecret": { "description": "DeployKeyAndSecret Holds generated public deploy key and shared secret", "type": "object",