Skip to content

Commit

Permalink
Merge pull request #2035 from FabianKramm/v0.20
Browse files Browse the repository at this point in the history
[Backport v0.20] backport missing commits
  • Loading branch information
deniseschannon authored Aug 6, 2024
2 parents 03f0d2c + 8e29359 commit cafdf6d
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 11 deletions.
1 change: 1 addition & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ generate-vcluster-images version="0.0.0":
generate-cli-docs:
go run -mod vendor -tags pro ./hack/docs/main.go

# Generate the vcluster.yaml config schema
generate-config-schema:
go run -mod vendor ./hack/schema/main.go

Expand Down
33 changes: 33 additions & 0 deletions chart/templates/_rbac.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,36 @@
{{- end }}
{{- end }}
{{- end -}}

{{/*
Whether to create a role and role binding to access the platform API key secret
*/}}
{{- define "vcluster.rbac.createPlatformSecretRole" -}}
{{- $createRBAC := dig "platform" "apiKey" "createRBAC" true .Values.external -}}
{{- if and $createRBAC (ne (include "vcluster.rbac.platformSecretNamespace" .) .Release.Namespace) }}
{{- true -}}
{{- end }}
{{- end -}}

{{/*
Namespace containing the vCluster platform secret
*/}}
{{- define "vcluster.rbac.platformSecretNamespace" -}}
{{- dig "platform" "apiKey" "namespace" .Release.Namespace .Values.external | default .Release.Namespace -}}
{{- end -}}

{{/*
Name specifies the secret name containing the vCluster platform licenses and tokens
*/}}
{{- define "vcluster.rbac.platformSecretName" -}}
{{- dig "platform" "apiKey" "secretName" "vcluster-platform-api-key" .Values.external | quote -}}
{{- end -}}

{{- define "vcluster.rbac.platformRoleName" -}}
{{- printf "vc-%s-v-%s-platform-role" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}


{{- define "vcluster.rbac.platformRoleBindingName" -}}
{{- printf "vc-%s-v-%s-platform-role-binding" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}
31 changes: 31 additions & 0 deletions chart/templates/platform-rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{{- if include "vcluster.rbac.createPlatformSecretRole" . }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "vcluster.rbac.platformRoleName" . }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames:
- {{ include "vcluster.rbac.platformSecretName" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "vcluster.rbac.platformRoleBindingName" . }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
subjects:
- kind: ServiceAccount
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
name: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
name: vc-{{ .Release.Name }}
{{- end }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
roleRef:
kind: Role
name: {{ include "vcluster.rbac.platformRoleName" . }}
apiGroup: rbac.authorization.k8s.io
{{- end }}
114 changes: 114 additions & 0 deletions chart/tests/platform-secret-role_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
suite: Platform Secret Role
templates:
- platform-rbac.yaml

tests:
- it: check explicitly disabled
set:
external:
platform:
apiKey:
namespace: "some-other-namespace"
createRBAC: false
asserts:
- hasDocuments:
count: 0

- it: check disabled on empty namespace
set:
external:
platform:
apiKey:
namespace: ""
asserts:
- hasDocuments:
count: 0

- it: check disabled on implicit same namespace
set:
external:
platform:
apiKey:
secretName: "some-other-secret"
asserts:
- hasDocuments:
count: 0

- it: automatically create role for specific secret for reading & patching
set:
external:
platform:
apiKey:
secretName: "my-secret-name"
namespace: "some-other-namespace"
asserts:
- hasDocuments:
count: 2
- documentIndex: 0
lengthEqual:
path: rules
count: 1
- documentIndex: 0
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role"
- documentIndex: 1
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role-binding"
- documentIndex: 0
contains:
path: rules
count: 1
content:
apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["my-secret-name"]
- documentIndex: 1
contains:
path: subjects
count: 1
content:
kind: ServiceAccount
name: vc-RELEASE-NAME
namespace: some-other-namespace

- it: automatically create role for default secret for reading & patching
set:
external:
platform:
apiKey:
namespace: "some-other-namespace"
asserts:
- hasDocuments:
count: 2
- documentIndex: 0
lengthEqual:
path: rules
count: 1
- documentIndex: 0
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role"
- documentIndex: 1
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role-binding"
- documentIndex: 0
contains:
path: rules
count: 1
content:
apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["vcluster-platform-api-key"]
- documentIndex: 1
contains:
path: subjects
count: 1
content:
kind: ServiceAccount
name: vc-RELEASE-NAME
namespace: some-other-namespace
2 changes: 1 addition & 1 deletion cmd/vclusterctl/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (cmd *ListCmd) Run(cobraCmd *cobra.Command) error {
return fmt.Errorf("parse driver type: %w", err)
}
if driverType == config.PlatformDriver {
return cli.ListPlatform(cobraCmd.Context(), &cmd.ListOptions, cmd.GlobalFlags, cmd.log)
return cli.ListPlatform(cobraCmd.Context(), &cmd.ListOptions, cmd.GlobalFlags, cmd.log, "")
}

return cli.ListHelm(cobraCmd.Context(), &cmd.ListOptions, cmd.GlobalFlags, cmd.log)
Expand Down
7 changes: 4 additions & 3 deletions cmd/vclusterctl/cmd/platform/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package list

import (
"github.com/loft-sh/api/v4/pkg/product"

"github.com/loft-sh/vcluster/pkg/cli/flags"
pdefaults "github.com/loft-sh/vcluster/pkg/platform/defaults"
"github.com/spf13/cobra"
)

// NewListCmd creates a new cobra command
func NewListCmd(globalFlags *flags.GlobalFlags) *cobra.Command {
func NewListCmd(globalFlags *flags.GlobalFlags, defaults *pdefaults.Defaults) *cobra.Command {
description := product.ReplaceWithHeader("list", "")
listCmd := &cobra.Command{
Use: "list",
Expand All @@ -18,9 +18,10 @@ func NewListCmd(globalFlags *flags.GlobalFlags) *cobra.Command {
}

listCmd.AddCommand(newClustersCmd(globalFlags))
listCmd.AddCommand(newProjectsCmd(globalFlags))
listCmd.AddCommand(newSharedSecretsCmd(globalFlags))
listCmd.AddCommand(newTeamsCmd(globalFlags))
listCmd.AddCommand(newVClustersCmd(globalFlags))
listCmd.AddCommand(newVClustersCmd(globalFlags, defaults))
listCmd.AddCommand(newNamespacesCmd(globalFlags))
return listCmd
}
75 changes: 75 additions & 0 deletions cmd/vclusterctl/cmd/platform/list/projects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package list

import (
"context"

"github.com/loft-sh/api/v4/pkg/product"
"github.com/loft-sh/log"
"github.com/loft-sh/log/table"
"github.com/loft-sh/vcluster/pkg/cli/flags"
"github.com/loft-sh/vcluster/pkg/platform"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ProjectsCmd holds the login cmd flags
type ProjectsCmd struct {
*flags.GlobalFlags

log log.Logger
}

// newProjectsCmd creates a new spaces command
func newProjectsCmd(globalFlags *flags.GlobalFlags) *cobra.Command {
cmd := &ProjectsCmd{
GlobalFlags: globalFlags,
log: log.GetInstance(),
}
description := product.ReplaceWithHeader("list projects", `
List the vcluster platform projects you have access to
Example:
vcluster platform list projects
########################################################
`)
projectsCmd := &cobra.Command{
Use: "projects",
Short: product.Replace("Lists the loft projects you have access to"),
Long: description,
Args: cobra.NoArgs,
RunE: func(cobraCmd *cobra.Command, _ []string) error {
return cmd.RunProjects(cobraCmd.Context())
},
}

return projectsCmd
}

// RunProjects executes the functionality
func (cmd *ProjectsCmd) RunProjects(ctx context.Context) error {
platformClient, err := platform.InitClientFromConfig(ctx, cmd.LoadedConfig(cmd.log))
if err != nil {
return err
}

managementClient, err := platformClient.Management()
if err != nil {
return err
}

projectList, err := managementClient.Loft().ManagementV1().Projects().List(ctx, metav1.ListOptions{})
if err != nil {
return err
}

header := []string{
"Project",
}
projects := make([][]string, len(projectList.Items))
for i, project := range projectList.Items {
projects[i] = []string{project.Name}
}

table.PrintTable(cmd.log, header, projects)
return nil
}
10 changes: 7 additions & 3 deletions cmd/vclusterctl/cmd/platform/list/vclusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/loft-sh/log"
"github.com/loft-sh/vcluster/pkg/cli"
"github.com/loft-sh/vcluster/pkg/cli/flags"
pdefaults "github.com/loft-sh/vcluster/pkg/platform/defaults"
"github.com/spf13/cobra"
)

Expand All @@ -14,11 +15,12 @@ type VClustersCmd struct {
*flags.GlobalFlags
cli.ListOptions

log log.Logger
log log.Logger
Project string
}

// newVClustersCmd creates a new command
func newVClustersCmd(globalFlags *flags.GlobalFlags) *cobra.Command {
func newVClustersCmd(globalFlags *flags.GlobalFlags, defaults *pdefaults.Defaults) *cobra.Command {
cmd := &VClustersCmd{
GlobalFlags: globalFlags,
log: log.GetInstance(),
Expand All @@ -42,11 +44,13 @@ vcluster platform list vclusters
},
}

p, _ := defaults.Get(pdefaults.KeyProject, "")
cobraCmd.Flags().StringVarP(&cmd.Project, "project", "p", p, "The project to use")
cobraCmd.Flags().StringVar(&cmd.Output, "output", "table", "Choose the format of the output. [table|json]")

return cobraCmd
}

func (cmd *VClustersCmd) Run(ctx context.Context) error {
return cli.ListPlatform(ctx, &cmd.ListOptions, cmd.GlobalFlags, cmd.log)
return cli.ListPlatform(ctx, &cmd.ListOptions, cmd.GlobalFlags, cmd.log, cmd.Project)
}
2 changes: 1 addition & 1 deletion cmd/vclusterctl/cmd/platform/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewPlatformCmd(globalFlags *flags.GlobalFlags) (*cobra.Command, error) {
platformCmd.AddCommand(NewAccessKeyCmd(globalFlags))
platformCmd.AddCommand(get.NewGetCmd(globalFlags, defaults))
platformCmd.AddCommand(connect.NewConnectCmd(globalFlags, defaults))
platformCmd.AddCommand(list.NewListCmd(globalFlags))
platformCmd.AddCommand(list.NewListCmd(globalFlags, defaults))
platformCmd.AddCommand(set.NewSetCmd(globalFlags, defaults))
platformCmd.AddCommand(backup.NewBackupCmd(globalFlags))
platformCmd.AddCommand(wakeup.NewWakeupCmd(globalFlags, defaults))
Expand Down
6 changes: 5 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1777,7 +1777,6 @@ type ExperimentalDeployHelmChart struct {

type PlatformConfig struct {
// APIKey defines where to find the platform access key and host. By default, vCluster will search in the following locations in this precedence:
// * platform.api.accessKey
// * environment variable called LICENSE
// * secret specified under external.platform.apiKey.secretName
// * secret called "vcluster-platform-api-key" in the vCluster namespace
Expand All @@ -1792,6 +1791,11 @@ type PlatformAPIKey struct {
// Namespace defines the namespace where the access key secret should be retrieved from. If this is not equal to the namespace
// where the vCluster instance is deployed, you need to make sure vCluster has access to this other namespace.
Namespace string `json:"namespace,omitempty"`

// CreateRBAC will automatically create the necessary RBAC roles and role bindings to allow vCluster to read the secret specified
// in the above namespace, if specified.
// This defaults to true.
CreateRBAC *bool `json:"createRBAC,omitempty"`
}

type ExperimentalGenericSync struct {
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/list_platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"k8s.io/client-go/tools/clientcmd"
)

func ListPlatform(ctx context.Context, options *ListOptions, globalFlags *flags.GlobalFlags, logger log.Logger) error {
func ListPlatform(ctx context.Context, options *ListOptions, globalFlags *flags.GlobalFlags, logger log.Logger, projectName string) error {
rawConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}).RawConfig()
if err != nil {
return err
Expand All @@ -27,7 +27,7 @@ func ListPlatform(ctx context.Context, options *ListOptions, globalFlags *flags.
return err
}

proVClusters, err := platform.ListVClusters(ctx, platformClient, "", "")
proVClusters, err := platform.ListVClusters(ctx, platformClient, "", projectName)
if err != nil {
return err
}
Expand Down

0 comments on commit cafdf6d

Please sign in to comment.