Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ dev-setup:
--set 'crds.exclusive=true'\
--set 'crds.createConfig=true'\
--set "webhooks.exclusive=true"\
--set "webhooks.hooks.nodes.enabled=true"\
--set "webhooks.service.url=$${WEBHOOK_URL}" \
--set "webhooks.service.caBundle=$${CA_BUNDLE}" \
capsule \
Expand Down Expand Up @@ -243,9 +244,12 @@ e2e-install-deps:
@$(KUBECTL) apply --force-conflicts --server-side=true -f https://github.com/$(API_GW_LOOKUP)/releases/download/$(API_GW_VERSION)/standard-install.yaml

e2e-build: kind
$(MAKE) e2e-build-cluster
$(MAKE) e2e-install

e2e-build-cluster: kind
$(KIND) create cluster --wait=60s --name $(CLUSTER_NAME) --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION)
$(MAKE) e2e-install-deps
$(MAKE) e2e-install

.PHONY: e2e-install
e2e-install: ko-build-all
Expand Down
17 changes: 9 additions & 8 deletions api/v1beta1/namespace_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"github.com/projectcapsule/capsule/pkg/api"
"github.com/projectcapsule/capsule/pkg/api/meta"
)

type NamespaceOptions struct {
Expand All @@ -18,23 +19,23 @@ type NamespaceOptions struct {
}

func (in *Tenant) hasForbiddenNamespaceLabelsAnnotations() bool {
if _, ok := in.Annotations[api.ForbiddenNamespaceLabelsAnnotation]; ok {
if _, ok := in.Annotations[meta.ForbiddenNamespaceLabelsAnnotation]; ok {
return true
}

if _, ok := in.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
if _, ok := in.Annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
return true
}

return false
}

func (in *Tenant) hasForbiddenNamespaceAnnotationsAnnotations() bool {
if _, ok := in.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; ok {
if _, ok := in.Annotations[meta.ForbiddenNamespaceAnnotationsAnnotation]; ok {
return true
}

if _, ok := in.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
if _, ok := in.Annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
return true
}

Expand All @@ -47,8 +48,8 @@ func (in *Tenant) ForbiddenUserNamespaceLabels() *api.ForbiddenListSpec {
}

return &api.ForbiddenListSpec{
Exact: strings.Split(in.Annotations[api.ForbiddenNamespaceLabelsAnnotation], ","),
Regex: in.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation],
Exact: strings.Split(in.Annotations[meta.ForbiddenNamespaceLabelsAnnotation], ","),
Regex: in.Annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation],
}
}

Expand All @@ -58,7 +59,7 @@ func (in *Tenant) ForbiddenUserNamespaceAnnotations() *api.ForbiddenListSpec {
}

return &api.ForbiddenListSpec{
Exact: strings.Split(in.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation], ","),
Regex: in.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation],
Exact: strings.Split(in.Annotations[meta.ForbiddenNamespaceAnnotationsAnnotation], ","),
Regex: in.Annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation],
}
}
5 changes: 5 additions & 0 deletions api/v1beta2/capsuleconfiguration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ type CapsuleConfigurationSpec struct {
// when not using an already provided CA and certificate, or when these are managed externally with Vault, or cert-manager.
// +kubebuilder:default=true
EnableTLSReconciler bool `json:"enableTLSReconciler"` //nolint:tagliatelle
// Define entities which can act as Administrators in the capsule construct
// These entities are automatically owners for all existing tenants. Meaning they can add namespaces to any tenant. However they must be specific by using the capsule label
// for interacting with namespaces. Because if that label is not defined, it's assumed that namespace interaction was not targeted towards a tenant and will therefor
// be ignored by capsule.
Administrators api.UserListSpec `json:"administrators,omitempty"`
}

type NodeMetadata struct {
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta2/resourcepool_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package v1beta2

import (
"errors"
"fmt"
"sort"

corev1 "k8s.io/api/core/v1"
Expand All @@ -13,6 +14,10 @@ import (
"github.com/projectcapsule/capsule/pkg/api"
)

func (r *ResourcePool) GetQuotaName() string {
return fmt.Sprintf("capsule-pool-%s", r.GetName())
}

func (r *ResourcePool) AssignNamespaces(namespaces []corev1.Namespace) {
var l []string

Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/resourcepool_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"k8s.io/apimachinery/pkg/types"

"github.com/projectcapsule/capsule/pkg/api"
"github.com/projectcapsule/capsule/pkg/meta"
"github.com/projectcapsule/capsule/pkg/api/meta"
"github.com/stretchr/testify/assert"
)

Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/resourcepoolclaim_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package v1beta2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/projectcapsule/capsule/pkg/meta"
"github.com/projectcapsule/capsule/pkg/api/meta"
)

// Indicate the claim is bound to a resource pool.
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/resourcepoolclaim_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package v1beta2
import (
"testing"

"github.com/projectcapsule/capsule/pkg/meta"
"github.com/projectcapsule/capsule/pkg/api/meta"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down
51 changes: 27 additions & 24 deletions api/v1beta2/tenant_conversion_hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

capsulev1beta1 "github.com/projectcapsule/capsule/api/v1beta1"
"github.com/projectcapsule/capsule/pkg/api"
"github.com/projectcapsule/capsule/pkg/api/meta"
)

func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
Expand All @@ -26,27 +27,29 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
}

in.ObjectMeta = src.ObjectMeta
in.Spec.Owners = make(OwnerListSpec, 0, len(src.Spec.Owners))
in.Spec.Owners = make(api.OwnerListSpec, 0, len(src.Spec.Owners))

for index, owner := range src.Spec.Owners {
proxySettings := make([]ProxySettings, 0, len(owner.ProxyOperations))
proxySettings := make([]api.ProxySettings, 0, len(owner.ProxyOperations))

for _, proxyOp := range owner.ProxyOperations {
ops := make([]ProxyOperation, 0, len(proxyOp.Operations))
ops := make([]api.ProxyOperation, 0, len(proxyOp.Operations))

for _, op := range proxyOp.Operations {
ops = append(ops, ProxyOperation(op))
ops = append(ops, api.ProxyOperation(op))
}

proxySettings = append(proxySettings, ProxySettings{
Kind: ProxyServiceKind(proxyOp.Kind),
proxySettings = append(proxySettings, api.ProxySettings{
Kind: api.ProxyServiceKind(proxyOp.Kind),
Operations: ops,
})
}

in.Spec.Owners = append(in.Spec.Owners, OwnerSpec{
Kind: OwnerKind(owner.Kind),
Name: owner.Name,
in.Spec.Owners = append(in.Spec.Owners, api.OwnerSpec{
UserSpec: api.UserSpec{
Kind: api.OwnerKind(owner.Kind),
Name: owner.Name,
},
ClusterRoles: owner.GetRoles(*src, index),
ProxyOperations: proxySettings,
})
Expand All @@ -59,28 +62,28 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {

in.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata

if value, found := annotations[api.ForbiddenNamespaceLabelsAnnotation]; found {
if value, found := annotations[meta.ForbiddenNamespaceLabelsAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenLabels.Exact = strings.Split(value, ",")

delete(annotations, api.ForbiddenNamespaceLabelsAnnotation)
delete(annotations, meta.ForbiddenNamespaceLabelsAnnotation)
}

if value, found := annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; found {
if value, found := annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenLabels.Regex = value

delete(annotations, api.ForbiddenNamespaceLabelsRegexpAnnotation)
delete(annotations, meta.ForbiddenNamespaceLabelsRegexpAnnotation)
}

if value, found := annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; found {
if value, found := annotations[meta.ForbiddenNamespaceAnnotationsAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenAnnotations.Exact = strings.Split(value, ",")

delete(annotations, api.ForbiddenNamespaceAnnotationsAnnotation)
delete(annotations, meta.ForbiddenNamespaceAnnotationsAnnotation)
}

if value, found := annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; found {
if value, found := annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenAnnotations.Regex = value

delete(annotations, api.ForbiddenNamespaceAnnotationsRegexpAnnotation)
delete(annotations, meta.ForbiddenNamespaceAnnotationsRegexpAnnotation)
}
}

Expand Down Expand Up @@ -144,10 +147,10 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
in.Spec.Cordoned = value
}

if _, found := annotations[api.ProtectedTenantAnnotation]; found {
if _, found := annotations[meta.ProtectedTenantAnnotation]; found {
in.Spec.PreventDeletion = true

delete(annotations, api.ProtectedTenantAnnotation)
delete(annotations, meta.ProtectedTenantAnnotation)
}

in.SetAnnotations(annotations)
Expand Down Expand Up @@ -215,19 +218,19 @@ func (in *Tenant) ConvertTo(raw conversion.Hub) error {
dst.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata

if exact := nsOpts.ForbiddenAnnotations.Exact; len(exact) > 0 {
annotations[api.ForbiddenNamespaceAnnotationsAnnotation] = strings.Join(exact, ",")
annotations[meta.ForbiddenNamespaceAnnotationsAnnotation] = strings.Join(exact, ",")
}

if regex := nsOpts.ForbiddenAnnotations.Regex; len(regex) > 0 {
annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation] = regex
annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation] = regex
}

if exact := nsOpts.ForbiddenLabels.Exact; len(exact) > 0 {
annotations[api.ForbiddenNamespaceLabelsAnnotation] = strings.Join(exact, ",")
annotations[meta.ForbiddenNamespaceLabelsAnnotation] = strings.Join(exact, ",")
}

if regex := nsOpts.ForbiddenLabels.Regex; len(regex) > 0 {
annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation] = regex
annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation] = regex
}
}

Expand Down Expand Up @@ -264,7 +267,7 @@ func (in *Tenant) ConvertTo(raw conversion.Hub) error {
}

if in.Spec.PreventDeletion {
annotations[api.ProtectedTenantAnnotation] = "true" //nolint:goconst
annotations[meta.ProtectedTenantAnnotation] = "true" //nolint:goconst
}

if in.Spec.Cordoned {
Expand Down
6 changes: 3 additions & 3 deletions api/v1beta2/tenant_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ func (in *Tenant) AssignNamespaces(namespaces []corev1.Namespace) {
in.Status.Size = uint(len(l))
}

func (in *Tenant) GetOwnerProxySettings(name string, kind OwnerKind) []ProxySettings {
func (in *Tenant) GetOwnerProxySettings(name string, kind api.OwnerKind) []api.ProxySettings {
return in.Spec.Owners.FindOwner(name, kind).ProxyOperations
}

// GetClusterRolePermissions returns a map where the clusterRole is the key
// and the value is a list of permission subjects (kind and name) that reference that role.
// These mappings are gathered from the owners and additionalRolebindings spec.
func (in *Tenant) GetSubjectsByClusterRoles(ignoreOwnerKind []OwnerKind) (rolePerms map[string][]rbacv1.Subject) {
func (in *Tenant) GetSubjectsByClusterRoles(ignoreOwnerKind []api.OwnerKind) (rolePerms map[string][]rbacv1.Subject) {
rolePerms = make(map[string][]rbacv1.Subject)

// Helper to add permissions for a given clusterRole
Expand Down Expand Up @@ -97,7 +97,7 @@ func (in *Tenant) GetSubjectsByClusterRoles(ignoreOwnerKind []OwnerKind) (rolePe
}

// Get the permissions for a tenant ordered by groups and users.
func (in *Tenant) GetClusterRolesBySubject(ignoreOwnerKind []OwnerKind) (maps map[string]map[string]api.TenantSubjectRoles) {
func (in *Tenant) GetClusterRolesBySubject(ignoreOwnerKind []api.OwnerKind) (maps map[string]map[string]api.TenantSubjectRoles) {
maps = make(map[string]map[string]api.TenantSubjectRoles)

// Initialize a nested map for kind ("User", "Group") and name
Expand Down
24 changes: 15 additions & 9 deletions api/v1beta2/tenant_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,26 @@ import (

var tenant = &Tenant{
Spec: TenantSpec{
Owners: []OwnerSpec{
Owners: []api.OwnerSpec{
{
Kind: "User",
Name: "user1",
UserSpec: api.UserSpec{
Kind: "User",
Name: "user1",
},
ClusterRoles: []string{"cluster-admin", "read-only"},
},
{
Kind: "Group",
Name: "group1",
UserSpec: api.UserSpec{
Kind: "Group",
Name: "group1",
},
ClusterRoles: []string{"edit"},
},
{
Kind: ServiceAccountOwner,
Name: "service",
UserSpec: api.UserSpec{
Kind: api.ServiceAccountOwner,
Name: "service",
},
ClusterRoles: []string{"read-only"},
},
},
Expand Down Expand Up @@ -96,7 +102,7 @@ func TestGetSubjectsByClusterRoles(t *testing.T) {
}

// Ignore SubjectTypes (Ignores ServiceAccounts)
ignored := tenant.GetSubjectsByClusterRoles([]OwnerKind{"ServiceAccount"})
ignored := tenant.GetSubjectsByClusterRoles([]api.OwnerKind{"ServiceAccount"})
expectedIgnored := map[string][]rbacv1.Subject{
"cluster-admin": {
{Kind: "User", Name: "user1"},
Expand Down Expand Up @@ -156,7 +162,7 @@ func TestGetClusterRolesBySubject(t *testing.T) {
}

delete(expected, "ServiceAccount")
ignored := tenant.GetClusterRolesBySubject([]OwnerKind{"ServiceAccount"})
ignored := tenant.GetClusterRolesBySubject([]api.OwnerKind{"ServiceAccount"})

if !reflect.DeepEqual(ignored, expected) {
t.Errorf("Expected %v, but got %v", expected, ignored)
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/tenant_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package v1beta2
import (
k8stypes "k8s.io/apimachinery/pkg/types"

"github.com/projectcapsule/capsule/pkg/meta"
"github.com/projectcapsule/capsule/pkg/api/meta"
)

// +kubebuilder:validation:Enum=Cordoned;Active
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/tenant_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
type TenantSpec struct {
// Specifies the owners of the Tenant.
// Optional
Owners OwnerListSpec `json:"owners,omitempty"`
Owners api.OwnerListSpec `json:"owners,omitempty"`
// Specifies options for the Namespaces, such as additional metadata or maximum number of namespaces allowed for that Tenant. Once the namespace quota assigned to the Tenant has been reached, the Tenant owner cannot create further namespaces. Optional.
NamespaceOptions *NamespaceOptions `json:"namespaceOptions,omitempty"`
// Specifies options for the Service, such as additional metadata or block of certain type of Services. Optional.
Expand Down
Loading