Skip to content

Commit

Permalink
Merge branch 'main' into willdavsmith/rad-run-dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
willdavsmith authored Feb 23, 2024
2 parents 470afa3 + 6885574 commit 4e491c2
Show file tree
Hide file tree
Showing 25 changed files with 431 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ concurrency:

env:
# Go version to install
GOVER: '^1.21'
GOVER: '1.21.7'

# gotestsum version - see: https://github.com/gotestyourself/gotestsum
GOTESTSUMVERSION: 1.10.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/functional-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ on:

env:
# Go version
GOVER: '^1.21'
GOVER: '1.21.7'
GOPROXY: https://proxy.golang.org

# gotestsum version - see: https://github.com/gotestyourself/gotestsum
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
GOVER: '^1.21'
GOVER: '1.21.7'
GOPROXY: https://proxy.golang.org
HELM_CHARTS_DIR: deploy/Chart
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/long-running-azure.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ on:

env:
# Go version
GOVER: "^1.21"
GOVER: "1.21.7"
GOPROXY: https://proxy.golang.org

# gotestsum version - see: https://github.com/gotestyourself/gotestsum
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'radius-project/radius'
env:
GOVER: '^1.21'
GOVER: '1.21.7'
GOPRIVATE: github.com/radius-project
steps:
- name: Checkout radius repository
Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pkg/cli/cmd/env/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (r *Runner) Validate(cmd *cobra.Command, args []string) error {
return err
}

err = r.NamespaceInterface.ValidateNamespace(cmd.Context(), r.Namespace)
err = r.NamespaceInterface.ValidateNamespace(cmd.Context(), r.Namespace, *r.Workspace)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/cmd/env/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,13 @@ func createMocksWithInvalidResourceGroup(namespaceClient *namespace.MockInterfac

func createValidateNamespaceSuccess(namespaceClient *namespace.MockInterface) {
namespaceClient.EXPECT().
ValidateNamespace(gomock.Any(), "testingenv").
ValidateNamespace(gomock.Any(), "testingenv", gomock.Any()).
Return(nil).Times(1)
}

func createValidateNamespaceError(namespaceClient *namespace.MockInterface) {
namespaceClient.EXPECT().
ValidateNamespace(gomock.Any(), gomock.Any()).
ValidateNamespace(gomock.Any(), gomock.Any(), gomock.Any()).
Return(fmt.Errorf("failed to create namespace")).Times(1)
}

Expand Down
9 changes: 5 additions & 4 deletions pkg/cli/cmd/env/namespace/mock_namespace.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions pkg/cli/cmd/env/namespace/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ package namespace
import (
"context"

"github.com/radius-project/radius/pkg/cli/clierrors"
"github.com/radius-project/radius/pkg/cli/kubernetes"
"github.com/radius-project/radius/pkg/cli/workspaces"
)

//go:generate mockgen -destination=./mock_namespace.go -package=namespace -self_package github.com/radius-project/radius/pkg/cli/cmd/env/namespace github.com/radius-project/radius/pkg/cli/cmd/env/namespace Interface
type Interface interface {
ValidateNamespace(ctx context.Context, namespace string) error
ValidateNamespace(ctx context.Context, namespace string, workspace workspaces.Workspace) error
}

type Impl struct {
Expand All @@ -35,8 +37,13 @@ type Impl struct {

// ValidateNamespace creates a Kubernetes client and checks if the given namespace exists. If it does not exist, creates it.
// If unsuccessful, returns an error.
func (i *Impl) ValidateNamespace(ctx context.Context, namespace string) error {
client, _, err := kubernetes.NewClientset("")
func (i *Impl) ValidateNamespace(ctx context.Context, namespace string, workspace workspaces.Workspace) error {
// get the current kubernetes context from the workspace
kubernetesContext, hasContext := workspace.KubernetesContext()
if !hasContext {
return clierrors.Message("no kubernetes context found in the current workspace")
}
client, _, err := kubernetes.NewClientset(kubernetesContext)
if err != nil {
return err
}
Expand Down
21 changes: 6 additions & 15 deletions pkg/corerp/api/v20231001preview/zz_generated_models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 3 additions & 26 deletions pkg/corerp/api/v20231001preview/zz_generated_models_serde.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 15 additions & 2 deletions pkg/corerp/frontend/controller/secretstores/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/radius-project/radius/pkg/armrpc/rest"
"github.com/radius-project/radius/pkg/corerp/datamodel"
"github.com/radius-project/radius/pkg/kubernetes"
"github.com/radius-project/radius/pkg/kubeutil"
rpv1 "github.com/radius-project/radius/pkg/rp/v1"
"github.com/radius-project/radius/pkg/to"
"github.com/radius-project/radius/pkg/ucp/resources"
Expand Down Expand Up @@ -184,6 +185,11 @@ func UpsertSecret(ctx context.Context, newResource, old *datamodel.SecretStore,
ref = old.Properties.Resource
}

// resource property cannot be empty for global scoped resource.
if newResource.Properties.BasicResourceProperties.IsGlobalScopedResource() && ref == "" {
return rest.NewBadRequestResponse("$.properties.resource cannot be empty for global scoped resource."), nil
}

ns, name, err := fromResourceID(ref)
if err != nil {
return nil, err
Expand All @@ -195,6 +201,12 @@ func UpsertSecret(ctx context.Context, newResource, old *datamodel.SecretStore,
}
}

// Create namespace if not exists.
err = kubeutil.PatchNamespace(ctx, options.KubeClient, ns)
if err != nil {
return nil, err
}

if name == "" {
name = newResource.Name
}
Expand All @@ -208,8 +220,9 @@ func UpsertSecret(ctx context.Context, newResource, old *datamodel.SecretStore,
ksecret := &corev1.Secret{}
err = options.KubeClient.Get(ctx, runtimeclient.ObjectKey{Namespace: ns, Name: name}, ksecret)
if apierrors.IsNotFound(err) {
// If resource in incoming request references resource, then the resource must exist.
if ref != "" {
// If resource in incoming request references resource, then the resource must exist for a application/environment scoped resource.
// For global scoped resource create the kubernetes resource if not exists.
if ref != "" && !newResource.Properties.BasicResourceProperties.IsGlobalScopedResource() {
return rest.NewBadRequestResponse(fmt.Sprintf("'%s' referenced resource does not exist.", ref)), nil
}
app, _ := resources.ParseResource(newResource.Properties.Application)
Expand Down
112 changes: 109 additions & 3 deletions pkg/corerp/frontend/controller/secretstores/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ const (
testEnvID = testRootScope + "/Applications.Core/environments/env0"
testAppID = testRootScope + "/Applications.Core/applications/app0"

testFileCertValueFrom = "secretstores_datamodel_cert_valuefrom.json"
testFileCertValue = "secretstores_datamodel_cert_value.json"
testFileGenericValue = "secretstores_datamodel_generic.json"
testFileCertValueFrom = "secretstores_datamodel_cert_valuefrom.json"
testFileCertValue = "secretstores_datamodel_cert_value.json"
testFileGenericValue = "secretstores_datamodel_generic.json"
testFileGenericValueGlobalScope = "secretstores_datamodel_global_scope.json"
testFileGenericValueInvalidResource = "secretstores_datamodel_global_scope_invalid_resource.json"
testFileGenericValueEmptyResource = "secretstores_datamodel_global_scope_empty_resource.json"
)

func TestGetNamespace(t *testing.T) {
Expand Down Expand Up @@ -466,6 +469,109 @@ func TestUpsertSecret(t *testing.T) {
require.Equal(t, "'app0-ns/secret1' of $.properties.resource must be same as 'app0-ns/secret0'.", r.Body.Error.Message)
})

t.Run("create a new secret resource with global scope", func(t *testing.T) {
ctrl := gomock.NewController(t)
sc := store.NewMockStorageClient(ctrl)

newResource := testutil.MustGetTestData[datamodel.SecretStore](testFileGenericValueGlobalScope)

opt := &controller.Options{
StorageClient: sc,
KubeClient: k8sutil.NewFakeKubeClient(nil),
}

_, err := ValidateAndMutateRequest(context.TODO(), newResource, nil, opt)
require.NoError(t, err)
_, err = UpsertSecret(context.TODO(), newResource, nil, opt)
require.NoError(t, err)

// assert
require.Equal(t, "test-namespace/secret0", newResource.Properties.Resource)
ksecret := &corev1.Secret{}

err = opt.KubeClient.Get(context.TODO(), runtimeclient.ObjectKey{Namespace: "test-namespace", Name: "secret0"}, ksecret)
require.NoError(t, err)

require.Equal(t, "dGxzLmNydA==", string(ksecret.Data["tls.crt"]))
require.Equal(t, "dGxzLmNlcnQK", string(ksecret.Data["tls.key"]))
require.Equal(t, "MTAwMDAwMDAtMTAwMC0xMDAwLTAwMDAtMDAwMDAwMDAwMDAw", string(ksecret.Data["servicePrincipalPassword"]))
require.Equal(t, rpv1.OutputResource{
LocalID: "Secret",
ID: resources_kubernetes.IDFromParts(
resources_kubernetes.PlaneNameTODO,
"",
resources_kubernetes.KindSecret,
"test-namespace",
"secret0"),
}, newResource.Properties.Status.OutputResources[0])
})

t.Run("create a new secret resource with invalid resource", func(t *testing.T) {
ctrl := gomock.NewController(t)
sc := store.NewMockStorageClient(ctrl)

newResource := testutil.MustGetTestData[datamodel.SecretStore](testFileGenericValueInvalidResource)

opt := &controller.Options{
StorageClient: sc,
KubeClient: k8sutil.NewFakeKubeClient(nil),
}

_, err := ValidateAndMutateRequest(context.TODO(), newResource, nil, opt)
require.NoError(t, err)
_, err = UpsertSecret(context.TODO(), newResource, nil, opt)
require.Error(t, err)
require.Equal(t, err.Error(), "no Kubernetes namespace")
})

t.Run("create a new secret resource with empty resource", func(t *testing.T) {
ctrl := gomock.NewController(t)
sc := store.NewMockStorageClient(ctrl)

newResource := testutil.MustGetTestData[datamodel.SecretStore](testFileGenericValueEmptyResource)

opt := &controller.Options{
StorageClient: sc,
KubeClient: k8sutil.NewFakeKubeClient(nil),
}

_, err := ValidateAndMutateRequest(context.TODO(), newResource, nil, opt)
require.NoError(t, err)
resp, err := UpsertSecret(context.TODO(), newResource, nil, opt)
require.NoError(t, err)

// assert
r := resp.(*rest.BadRequestResponse)
require.Equal(t, "$.properties.resource cannot be empty for global scoped resource.", r.Body.Error.Message)
})

t.Run("add secret values to the existing secret store 1 ", func(t *testing.T) {
newResource := testutil.MustGetTestData[datamodel.SecretStore](testFileCertValue)
newResource.Properties.Resource = "default/secret"

opt := &controller.Options{
KubeClient: k8sutil.NewFakeKubeClient(nil),
}

resp, _ := UpsertSecret(context.TODO(), newResource, nil, opt)
r := resp.(*rest.BadRequestResponse)
require.Equal(t, "'default/secret' referenced resource does not exist.", r.Body.Error.Message)
})

t.Run("inherit old resource id for global scoped resource", func(t *testing.T) {
oldResource := testutil.MustGetTestData[datamodel.SecretStore](testFileGenericValueGlobalScope)
newResource := testutil.MustGetTestData[datamodel.SecretStore](testFileGenericValueEmptyResource)

opt := &controller.Options{
KubeClient: k8sutil.NewFakeKubeClient(nil),
}

_, err := UpsertSecret(context.TODO(), newResource, oldResource, opt)
require.NoError(t, err)

// assert
require.Equal(t, oldResource.Properties.Resource, newResource.Properties.Resource)
})
}

func TestDeleteSecret(t *testing.T) {
Expand Down
Loading

0 comments on commit 4e491c2

Please sign in to comment.