Skip to content

Commit

Permalink
Add certificate automation status (#613)
Browse files Browse the repository at this point in the history
* use operator util function to get TLS cert secret name

* add master branch to PR github action

* revert github action changes

* add certclient to test account struct

* start implementation of cert request status

* parse tls automation info from cert and certrequest

* generate swagger

* change tls automation status rules

* define annotation key in const

* tls automation status tests

* fix linter warnings

* fix spelling in function name
  • Loading branch information
nilsgstrabo authored Apr 10, 2024
1 parent 5d2214b commit 4c3e879
Show file tree
Hide file tree
Showing 31 changed files with 1,085 additions and 162 deletions.
10 changes: 6 additions & 4 deletions api/alerting/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"
"time"

certclientfake "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/fake"
alertModels "github.com/equinor/radix-api/api/alerting/models"
"github.com/equinor/radix-api/models"
radixmodels "github.com/equinor/radix-common/models"
Expand All @@ -27,10 +28,11 @@ type HandlerTestSuite struct {
}

func (s *HandlerTestSuite) SetupTest() {
inKubeClient, outKubeClient := kubefake.NewSimpleClientset(), kubefake.NewSimpleClientset()
inRadixClient, outRadixClient := radixfake.NewSimpleClientset(), radixfake.NewSimpleClientset()
inSecretProviderClient, outSecretProviderClient := secretproviderfake.NewSimpleClientset(), secretproviderfake.NewSimpleClientset()
s.accounts = models.NewAccounts(inKubeClient, inRadixClient, inSecretProviderClient, nil, outKubeClient, outRadixClient, outSecretProviderClient, nil, "", radixmodels.Impersonation{})
kubeClient := kubefake.NewSimpleClientset()
radixClient := radixfake.NewSimpleClientset()
secretProviderClient := secretproviderfake.NewSimpleClientset()
certClient := certclientfake.NewSimpleClientset()
s.accounts = models.NewAccounts(kubeClient, radixClient, secretProviderClient, nil, certClient, kubeClient, radixClient, secretProviderClient, nil, certClient, "", radixmodels.Impersonation{})
}

func TestHandlerTestSuite(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion api/applications/applications_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ func (ac *applicationController) ShowApplications(accounts models.Accounts, w ht
return
}

ac.JSONResponse(w, r, appRegistrations)}
ac.JSONResponse(w, r, appRegistrations)
}

// SearchApplications Gets applications by list of application names
func (ac *applicationController) SearchApplications(accounts models.Accounts, w http.ResponseWriter, r *http.Request) {
Expand Down
26 changes: 13 additions & 13 deletions api/applications/applications_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@ import (
commontest "github.com/equinor/radix-operator/pkg/apis/test"
builders "github.com/equinor/radix-operator/pkg/apis/utils"
"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/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubernetes "k8s.io/client-go/kubernetes"
kubefake "k8s.io/client-go/kubernetes/fake"
secretsstorevclient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned"
secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake"
)

Expand All @@ -51,7 +49,7 @@ const (
subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c"
)

func setupTest(t *testing.T, requireAppConfigurationItem, requireAppADGroups bool) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, prometheusclient.Interface, secretsstorevclient.Interface, *certfake.Clientset) {
func setupTest(t *testing.T, requireAppConfigurationItem, requireAppADGroups bool) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, *prometheusfake.Clientset, *secretproviderfake.Clientset, *certfake.Clientset) {
return setupTestWithFactory(t, newTestApplicationHandlerFactory(
ApplicationHandlerConfig{RequireAppConfigurationItem: requireAppConfigurationItem, RequireAppADGroups: requireAppADGroups},
func(ctx context.Context, kubeClient kubernetes.Interface, namespace string, configMapName string) (bool, error) {
Expand All @@ -60,7 +58,7 @@ func setupTest(t *testing.T, requireAppConfigurationItem, requireAppADGroups boo
))
}

func setupTestWithFactory(t *testing.T, handlerFactory ApplicationHandlerFactory) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, prometheusclient.Interface, secretsstorevclient.Interface, *certfake.Clientset) {
func setupTestWithFactory(t *testing.T, handlerFactory ApplicationHandlerFactory) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *fake.Clientset, *prometheusfake.Clientset, *secretproviderfake.Clientset, *certfake.Clientset) {
// Setup
kubeclient := kubefake.NewSimpleClientset()
radixclient := fake.NewSimpleClientset()
Expand All @@ -79,6 +77,7 @@ func setupTestWithFactory(t *testing.T, handlerFactory ApplicationHandlerFactory
kubeclient,
radixclient,
secretproviderclient,
certClient,
NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return true, nil
Expand All @@ -91,7 +90,7 @@ func setupTestWithFactory(t *testing.T, handlerFactory ApplicationHandlerFactory
}

func TestGetApplications_HasAccessToSomeRR(t *testing.T) {
commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient, _ := setupTest(t, true, true)
commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient, certClient := setupTest(t, true, true)

_, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration().
WithCloneURL("[email protected]:Equinor/my-app.git"))
Expand All @@ -105,6 +104,7 @@ func TestGetApplications_HasAccessToSomeRR(t *testing.T) {
kubeclient,
radixclient,
secretproviderclient,
certClient,
NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return false, nil
Expand All @@ -122,7 +122,7 @@ func TestGetApplications_HasAccessToSomeRR(t *testing.T) {
})

t.Run("access to single app", func(t *testing.T) {
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewApplicationController(
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, rr v1.RadixRegistration) (bool, error) {
return rr.GetName() == "my-second-app", nil
}, newTestApplicationHandlerFactory(ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: true},
Expand All @@ -139,7 +139,7 @@ func TestGetApplications_HasAccessToSomeRR(t *testing.T) {
})

t.Run("access to all app", func(t *testing.T) {
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewApplicationController(
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return true, nil
}, newTestApplicationHandlerFactory(ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: true},
Expand Down Expand Up @@ -197,7 +197,7 @@ func TestGetApplications_WithFilterOnSSHRepo_Filter(t *testing.T) {

func TestSearchApplicationsPost(t *testing.T) {
// Setup
commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient, _ := setupTest(t, true, true)
commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient, certClient := setupTest(t, true, true)
appNames := []string{"app-1", "app-2"}

for _, appName := range appNames {
Expand All @@ -219,7 +219,7 @@ func TestSearchApplicationsPost(t *testing.T) {
)
require.NoError(t, err)

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewApplicationController(
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return true, nil
}, newTestApplicationHandlerFactory(ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: true},
Expand Down Expand Up @@ -301,7 +301,7 @@ func TestSearchApplicationsPost(t *testing.T) {
})

t.Run("search for "+appNames[0]+" - no access", func(t *testing.T) {
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewApplicationController(
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return false, nil
}, newTestApplicationHandlerFactory(ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: true},
Expand Down Expand Up @@ -374,7 +374,7 @@ func TestSearchApplicationsPost_WithJobs_ShouldOnlyHaveLatest(t *testing.T) {

func TestSearchApplicationsGet(t *testing.T) {
// Setup
commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient, _ := setupTest(t, true, true)
commonTestUtils, _, kubeclient, radixclient, _, secretproviderclient, certClient := setupTest(t, true, true)
appNames := []string{"app-1", "app-2"}

for _, appName := range appNames {
Expand All @@ -396,7 +396,7 @@ func TestSearchApplicationsGet(t *testing.T) {
)
require.NoError(t, err)

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewApplicationController(
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return true, nil
}, newTestApplicationHandlerFactory(ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: true},
Expand Down Expand Up @@ -468,7 +468,7 @@ func TestSearchApplicationsGet(t *testing.T) {
})

t.Run("search for "+appNames[0]+" - no access", func(t *testing.T) {
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewApplicationController(
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewApplicationController(
func(_ context.Context, _ kubernetes.Interface, _ v1.RadixRegistration) (bool, error) {
return false, nil
}, newTestApplicationHandlerFactory(ApplicationHandlerConfig{RequireAppConfigurationItem: true, RequireAppADGroups: true},
Expand Down
12 changes: 6 additions & 6 deletions api/buildsecrets/buildsecrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import (
"github.com/stretchr/testify/require"
secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake"

certclientfake "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/fake"
"github.com/equinor/radix-api/api/buildsecrets/models"
controllertest "github.com/equinor/radix-api/api/test"
"github.com/equinor/radix-api/api/utils"
commontest "github.com/equinor/radix-operator/pkg/apis/test"
builders "github.com/equinor/radix-operator/pkg/apis/utils"
radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned"
"github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake"
radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake"
"github.com/stretchr/testify/assert"
"k8s.io/client-go/kubernetes"
kubefake "k8s.io/client-go/kubernetes/fake"
)

Expand All @@ -28,18 +27,19 @@ const (
subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c"
)

func setupTest(t *testing.T) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface) {
func setupTest(t *testing.T) (*commontest.Utils, *controllertest.Utils, *kubefake.Clientset, *radixfake.Clientset) {
// Setup
kubeclient := kubefake.NewSimpleClientset()
radixclient := fake.NewSimpleClientset()
radixclient := radixfake.NewSimpleClientset()
secretproviderclient := secretproviderfake.NewSimpleClientset()
certClient := certclientfake.NewSimpleClientset()

// commonTestUtils is used for creating CRDs
commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient)
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())
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewBuildSecretsController())

return &commonTestUtils, &controllerTestUtils, kubeclient, radixclient
}
Expand Down
22 changes: 12 additions & 10 deletions api/buildstatus/build_status_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import (
"github.com/stretchr/testify/require"
secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake"

certclientfake "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/fake"
controllertest "github.com/equinor/radix-api/api/test"
"github.com/equinor/radix-api/api/test/mock"
"github.com/equinor/radix-operator/pkg/apis/defaults"
v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1"
commontest "github.com/equinor/radix-operator/pkg/apis/test"
builders "github.com/equinor/radix-operator/pkg/apis/utils"
"github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake"
radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
kubefake "k8s.io/client-go/kubernetes/fake"
Expand All @@ -28,23 +29,24 @@ const (
subscriptionId = "12347718-c8f8-4995-bfbb-02655ff1f89c"
)

func setupTest(t *testing.T) (*commontest.Utils, *kubefake.Clientset, *fake.Clientset, *secretproviderfake.Clientset) {
func setupTest(t *testing.T) (*commontest.Utils, *kubefake.Clientset, *radixfake.Clientset, *secretproviderfake.Clientset, *certclientfake.Clientset) {
// Setup
kubeclient := kubefake.NewSimpleClientset()
radixclient := fake.NewSimpleClientset()
radixclient := radixfake.NewSimpleClientset()
secretproviderclient := secretproviderfake.NewSimpleClientset()
certClient := certclientfake.NewSimpleClientset()

// commonTestUtils is used for creating CRDs
commonTestUtils := commontest.NewTestUtils(kubeclient, radixclient, secretproviderclient)
err := commonTestUtils.CreateClusterPrerequisites(clusterName, egressIps, subscriptionId)
require.NoError(t, err)
_ = os.Setenv(defaults.ActiveClusternameEnvironmentVariable, clusterName)

return &commonTestUtils, kubeclient, radixclient, secretproviderclient
return &commonTestUtils, kubeclient, radixclient, secretproviderclient, certClient
}

func TestGetBuildStatus(t *testing.T) {
commonTestUtils, kubeclient, radixclient, secretproviderclient := setupTest(t)
commonTestUtils, kubeclient, radixclient, secretproviderclient, certClient := setupTest(t)

jobStartReferenceTime := time.Date(2020, 1, 10, 0, 0, 0, 0, time.UTC)
_, err := commonTestUtils.ApplyRegistration(builders.ARadixRegistration())
Expand Down Expand Up @@ -101,7 +103,7 @@ func TestGetBuildStatus(t *testing.T) {
Return(expected, nil).
Times(1)

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewBuildStatusController(fakeBuildStatus))
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewBuildStatusController(fakeBuildStatus))

responseChannel := controllerTestUtils.ExecuteUnAuthorizedRequest("GET", "/api/v1/applications/my-app/environments/test/buildstatus")
response := <-responseChannel
Expand Down Expand Up @@ -130,7 +132,7 @@ func TestGetBuildStatus(t *testing.T) {
return nil, nil
})

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewBuildStatusController(fakeBuildStatus))
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewBuildStatusController(fakeBuildStatus))

responseChannel := controllerTestUtils.ExecuteUnAuthorizedRequest("GET", "/api/v1/applications/my-app/environments/test/buildstatus")
response := <-responseChannel
Expand Down Expand Up @@ -158,7 +160,7 @@ func TestGetBuildStatus(t *testing.T) {
return nil, nil
})

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewBuildStatusController(fakeBuildStatus))
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewBuildStatusController(fakeBuildStatus))

responseChannel := controllerTestUtils.ExecuteUnAuthorizedRequest("GET", "/api/v1/applications/my-app/environments/test/buildstatus?pipeline=deploy")
response := <-responseChannel
Expand Down Expand Up @@ -186,7 +188,7 @@ func TestGetBuildStatus(t *testing.T) {
return nil, nil
})

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewBuildStatusController(fakeBuildStatus))
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewBuildStatusController(fakeBuildStatus))

responseChannel := controllerTestUtils.ExecuteUnAuthorizedRequest("GET", "/api/v1/applications/my-app/environments/test/buildstatus?pipeline=promote")
response := <-responseChannel
Expand All @@ -208,7 +210,7 @@ func TestGetBuildStatus(t *testing.T) {
Return(nil, errors.New("error")).
Times(1)

controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, NewBuildStatusController(fakeBuildStatus))
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixclient, secretproviderclient, certClient, NewBuildStatusController(fakeBuildStatus))

responseChannel := controllerTestUtils.ExecuteUnAuthorizedRequest("GET", "/api/v1/applications/my-app/environments/test/buildstatus")
response := <-responseChannel
Expand Down
2 changes: 1 addition & 1 deletion api/deployments/deployment_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func createGetLogEndpoint(appName, podName string) string {
func setupTest(t *testing.T) (*commontest.Utils, *controllertest.Utils, kubernetes.Interface, radixclient.Interface, prometheusclient.Interface, secretsstorevclient.Interface, *certfake.Clientset) {
commonTestUtils, kubeclient, radixClient, prometheusClient, secretproviderclient, certClient := apiUtils.SetupTest(t)
// controllerTestUtils is used for issuing HTTP request and processing responses
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixClient, secretproviderclient, NewDeploymentController())
controllerTestUtils := controllertest.NewTestUtils(kubeclient, radixClient, secretproviderclient, certClient, NewDeploymentController())
return commonTestUtils, &controllerTestUtils, kubeclient, radixClient, prometheusClient, secretproviderclient, certClient
}
func TestGetPodLog_no_radixconfig(t *testing.T) {
Expand Down
35 changes: 35 additions & 0 deletions api/deployments/models/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type TLS struct {
// required: true
UseAutomation bool `json:"useAutomation"`

// Automation describes the current condition of a certificate automation request
// Only set if UseAutomation is true
//
// required: false
Automation *TLSAutomation `json:"automation,omitempty"`

// Status of TLS certificate and private key
//
// required: true
Expand All @@ -44,6 +50,35 @@ type TLS struct {
Certificates []X509Certificate `json:"certificates,omitempty"`
}

// swagger:enum TLSAutomationStatusEnum
type TLSAutomationStatusEnum string

const (
// Certificate automation request pending
TLSAutomationPending TLSAutomationStatusEnum = "Pending"

// Certificate automation request succeeded
TLSAutomationSuccess TLSAutomationStatusEnum = "Success"

// Certificate automation request failed
TLSAutomationFailed TLSAutomationStatusEnum = "Failed"
)

// TLSAutomation describes the current condition of TLS automation
// swagger:model TLSAutomation
type TLSAutomation struct {
// Status of certificate automation request
//
// required: true
// example: Pending
Status TLSAutomationStatusEnum `json:"status"`

// Message is a human readable description of the reason for the status
//
// required: false
Message string `json:"message"`
}

// X509Certificate holds information about a X509 certificate
// swagger:model X509Certificate
type X509Certificate struct {
Expand Down
Loading

0 comments on commit 4c3e879

Please sign in to comment.