Skip to content
Open
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ dev-setup:
--create-namespace \
--set 'crds.install=true' \
--set 'crds.exclusive=true'\
--set 'crds.createConfig=true'\
--set 'crds.createConfig=true'\
--set "webhooks.exclusive=true"\
--set "webhooks.service.url=$${WEBHOOK_URL}" \
--set "webhooks.service.caBundle=$${CA_BUNDLE}" \
Expand Down
2 changes: 2 additions & 0 deletions api/v1beta2/capsuleconfiguration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ 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 Kubernetes-Client Configurations
ServiceAccountClient *api.ServiceAccountClient `json:"serviceAccountClient,omitempty"`
}

type NodeMetadata struct {
Expand Down
41 changes: 39 additions & 2 deletions api/v1beta2/tenantresource_global.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"

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

// GlobalTenantResourceSpec defines the desired state of GlobalTenantResource.
type GlobalTenantResourceSpec struct {
TenantResourceSpec `json:",inline"`
// Resource Scope, Can either be
// - Cluster: Just once per cluster
// - Tenant: Create Resources for each tenant in selected Tenants
// - Namespace: Create Resources for each namespace in selected Tenants
// +kubebuilder:default:=Namespace
Scope api.ResourceScope `json:"scope"`

// Defines the Tenant selector used target the tenants on which resources must be propagated.
TenantSelector metav1.LabelSelector `json:"tenantSelector,omitempty"`
TenantSelector metav1.LabelSelector `json:"tenantSelector,omitempty"`
TenantResourceSpec `json:",inline"`

Check failure on line 25 in api/v1beta2/tenantresource_global.go

View workflow job for this annotation

GitHub Actions / lint

embedded fields should be listed before regular fields (embeddedstructfieldcheck)
}

// GlobalTenantResourceStatus defines the observed state of GlobalTenantResource.
Expand All @@ -22,6 +31,31 @@
SelectedTenants []string `json:"selectedTenants"`
// List of the replicated resources for the given TenantResource.
ProcessedItems ProcessedItems `json:"processedItems"`
// Condition of the GlobalTenantResource.
Condition api.Condition `json:"condition,omitempty"`
}

func (p *GlobalTenantResource) SetCondition() {
failures := 0

for _, item := range p.Status.ProcessedItems {
if item.Status != metav1.ConditionTrue {
failures++
}
}

cond := meta.NewReadyCondition(p)
if failures > 0 {
cond.Status = metav1.ConditionFalse
cond.Reason = meta.FailedReason
cond.Message = "Reconcile completed with errors"

Check failure on line 51 in api/v1beta2/tenantresource_global.go

View workflow job for this annotation

GitHub Actions / lint

string `Reconcile completed with errors` has 2 occurrences, make it a constant (goconst)
} else {
cond.Status = metav1.ConditionTrue
cond.Reason = meta.SucceededReason
cond.Message = "Reconcile completed successfully"

Check failure on line 55 in api/v1beta2/tenantresource_global.go

View workflow job for this annotation

GitHub Actions / lint

string `Reconcile completed successfully` has 2 occurrences, make it a constant (goconst)
}

p.Status.Condition.UpdateCondition(cond)
}

type ProcessedItems []ObjectReferenceStatus
Expand All @@ -39,6 +73,9 @@
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.condition.type",description="Status for claim"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.condition.reason",description="Reason for status"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""

// GlobalTenantResource allows to propagate resource replications to a specific subset of Tenant resources.
type GlobalTenantResource struct {
Expand Down
32 changes: 32 additions & 0 deletions api/v1beta2/tenantresource_namespaced.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"

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

// TenantResourceSpec defines the desired state of TenantResource.
Expand All @@ -22,6 +23,9 @@ type TenantResourceSpec struct {
PruningOnDelete *bool `json:"pruningOnDelete,omitempty"`
// Defines the rules to select targeting Namespace, along with the objects that must be replicated.
Resources []ResourceSpec `json:"resources"`
// Local ServiceAccount which will perform all the actions defined in the TenantResource
// You must provide permissions accordingly to that ServiceAccount
ServiceAccount *api.ServiceAccountReference `json:"serviceAccount,omitempty"`
}

type ResourceSpec struct {
Expand All @@ -47,10 +51,38 @@ type RawExtension struct {
type TenantResourceStatus struct {
// List of the replicated resources for the given TenantResource.
ProcessedItems ProcessedItems `json:"processedItems"`
// Condition of the TenantResource.
Condition api.Condition `json:"condition,omitempty"`
}

func (p *TenantResource) SetCondition() {
failures := 0

for _, item := range p.Status.ProcessedItems {
if item.Status != metav1.ConditionTrue {
failures++
}
}

cond := meta.NewReadyCondition(p)
if failures > 0 {
cond.Status = metav1.ConditionFalse
cond.Reason = meta.FailedReason
cond.Message = "Reconcile completed with errors"
} else {
cond.Status = metav1.ConditionTrue
cond.Reason = meta.SucceededReason
cond.Message = "Reconcile completed successfully"
}

p.Status.Condition.UpdateCondition(cond)
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.condition.type",description="Status for claim"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.condition.reason",description="Reason for status"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""

// TenantResource allows a Tenant Owner, if enabled with proper RBAC, to propagate resources in its Namespace.
// The object must be deployed in a Tenant Namespace, and cannot reference object living in non-Tenant namespaces.
Expand Down
46 changes: 44 additions & 2 deletions api/v1beta2/tenantresource_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"fmt"
"strings"

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

Check failure on line 10 in api/v1beta2/tenantresource_types.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gci)
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -27,6 +28,29 @@
// Name of the referent.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
Name string `json:"name"`
// Tenant of the referent.
Tenant string `json:"tenant,omitempty"`
// status of the condition, one of True, False, Unknown.
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=True;False;Unknown
Status metav1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status"`
// message is a human readable message indicating details about the transition.
// This may be an empty string.
// +kubebuilder:validation:MaxLength=32768
Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
// type of condition in CamelCase or in foo.example.com/CamelCase.
// ---
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
// useful (see .node.status.conditions), the ability to deconflict is important.
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
// +kubebuilder:validation:MaxLength=316
Type string `json:"type" protobuf:"bytes,1,opt,name=type"`
// Resource Scope
Scope api.ResourceScope `json:"scope,omitempty"`
}

type ObjectReference struct {
Expand All @@ -37,13 +61,15 @@
}

func (in *ObjectReferenceStatus) String() string {
return fmt.Sprintf("Kind=%s,APIVersion=%s,Namespace=%s,Name=%s", in.Kind, in.APIVersion, in.Namespace, in.Name)
return fmt.Sprintf(
"Kind=%s,APIVersion=%s,Tenant=%s,Namespace=%s,Name=%s,Status=%s,Message=%s,Type=%s",
in.Kind, in.APIVersion, in.Tenant, in.Namespace, in.Name, in.Status, in.Message, in.Type)
}

func (in *ObjectReferenceStatus) ParseFromString(value string) error {
rawParts := strings.Split(value, ",")

if len(rawParts) != 4 {
if len(rawParts) != 8 {
return fmt.Errorf("unexpected raw parts")
}

Expand All @@ -61,10 +87,26 @@
in.Kind = v
case "APIVersion":
in.APIVersion = v
case "Tenant":
in.Tenant = v
case "Namespace":
in.Namespace = v
case "Name":
in.Name = v
case "Status":
switch metav1.ConditionStatus(v) {
case metav1.ConditionTrue, metav1.ConditionFalse, metav1.ConditionUnknown:
in.Status = metav1.ConditionStatus(v)
default:
return fmt.Errorf("invalid status value: %q", v)
}
case "Message":
in.Message = v
case "Type":
in.Type = v
case "Scope":
in.Scope = api.ResourceScope(v)

default:
return fmt.Errorf("unrecognized marker: %s", k)
}
Expand Down
14 changes: 13 additions & 1 deletion api/v1beta2/zz_generated.deepcopy.go

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

2 changes: 2 additions & 0 deletions charts/capsule/ci/proxy-values.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
proxy:
enabled: true
manager:
options:
useProxyForServiceAccountClient: true
resources:
requests:
cpu: 200m
Expand Down
47 changes: 47 additions & 0 deletions charts/capsule/crds/capsule.clastix.io_capsuleconfigurations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,53 @@ spec:
description: Disallow creation of namespaces, whose name matches this
regexp
type: string
serviceAccountClient:
description: Define Kubernetes-Client Configurations
properties:
caSecretKey:
default: ca.crt
description: Key in the secret that holds the CA certificate (e.g.,
"ca.crt")
type: string
caSecretName:
description: Name of the secret containing the CA certificate
type: string
caSecretNamespace:
description: Namespace where the CA certificate secret is located
type: string
endpoint:
description: Kubernetes API Endpoint to use for impersonation
type: string
globalDefaultServiceAccount:
description: |-
Default ServiceAccount for global resources (GlobalTenantResource)
When defined, users are required to use this ServiceAccount anywhere in the cluster
unless they explicitly provide their own.
maxLength: 253
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
globalDefaultServiceAccountNamespace:
description: |-
Default ServiceAccount for global resources (GlobalTenantResource)
When defined, users are required to use this ServiceAccount anywhere in the cluster
unless they explicitly provide their own.
maxLength: 253
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
skipTlsVerify:
default: false
description: If true, TLS certificate verification is skipped
(not recommended for production)
type: boolean
tenantDefaultServiceAccount:
description: |-
Default ServiceAccount for namespaced resources (TenantResource)
When defined, users are required to use this ServiceAccount within the namespace
where they deploy the resource, unless they explicitly provide their own.
maxLength: 253
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
userGroups:
default:
- capsule.clastix.io
Expand Down
Loading
Loading