Skip to content

Commit

Permalink
merge secretrefs and configrefs into single list (#81)
Browse files Browse the repository at this point in the history
<!-- markdownlint-disable MD041 -->
#### What this PR does / why we need it
This PR merges config ref and secret ref into a single list and
exchanges the implicit defaulting mechanism (implicitly inheriting the
configuration of the previous object in the pipeline - e.g. component
inherits from repository) with an explicit mechanism.

**Merging into single list**
The order in which the configuration is applied is relevant. This
becomes confusing and cumbersome with two separate lists and additional
mechanisms would be needed.

**Changing the defaulting mechanism**
1) The previous defaulting mechanism would automatically inherit the
referenced config maps if the config maps were empty and the secrets if
the secrets are empty. This does not make too much sense (but was
overseen, since originally, this was already intended as a single list).
If a user would provide all his configuration data in secrets and
therefore, doesn't specify any config maps, the mechanism would still
have inherited the config maps and potentially overwritten some of the
configs provided in the secret.
2) The new mechanism allows to only inherit parts of the configuration.
Thus, inherit the reference to config map a BUT NOT the reference to
config map b. This is useful, because the e.g. the Replication needs the
same credentials as the Component (since it needs to have access to the
component), but it does not need other parts of the configuration such
as the signing keys.

#### Which issue(s) this PR fixes
<!--
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->
#80
  • Loading branch information
fabianburth authored Jan 15, 2025
1 parent f09489a commit 1b31e29
Show file tree
Hide file tree
Showing 35 changed files with 1,832 additions and 1,369 deletions.
3 changes: 3 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ issues:
- source: "https://"
linters:
- lll
- source: "^// \\+kubebuilder:*"
linters:
- lll
- path: pkg/defaults/
linters:
- lll
Expand Down
27 changes: 27 additions & 0 deletions api/v1alpha1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,38 @@ limitations under the License.
package v1alpha1

import (
"github.com/fluxcd/pkg/apis/meta"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
ocmv1 "ocm.software/ocm/api/ocm/compdesc/meta/v1"
)

type ConfigurationPolicy string

const (
ConfigurationPolicyPropagate ConfigurationPolicy = "Propagate"
ConfigurationPolicyDoNotPropagate ConfigurationPolicy = "DoNotPropagate"
)

// OCMConfiguration defines a configuration applied to the reconciliation of an
// ocm k8s object as well as the policy for its propagation of this
// configuration.
// +kubebuilder:validation:XValidation:rule="((!has(self.apiVersion) || self.apiVersion == \"\" || self.apiVersion == \"v1\") && (self.kind == \"Secret\" || self.kind == \"ConfigMap\")) || (self.apiVersion == \"delivery.ocm.software/v1alpha1\" && (self.kind == \"OCMRepository\" || self.kind == \"Component\" || self.kind == \"Resource\" || self.kind == \"Replication\"))",message="apiVersion must be one of \"v1\" with kind \"Secret\" or \"ConfigMap\" or \"delivery.ocm.software/v1alpha1\" with the kind of an OCM kubernetes object"
type OCMConfiguration struct {
// Ref reference config maps or secrets containing arbitrary
// ocm config data (in the ocm config file format), or other configurable
// ocm api objects (OCMRepository, Component, Resource) to
// reuse their propagated configuration.
meta.NamespacedObjectKindReference `json:",inline"`
// Policy affects the propagation behavior of the configuration. If set to
// ConfigurationPolicyPropagate other ocm api objects can reference this
// object to reuse this configuration.
// +kubebuilder:validation:Enum:="Propagate";"DoNotPropagate"
// +kubebuilder:default:="DoNotPropagate"
// +required
Policy ConfigurationPolicy `json:"policy,omitempty"`
}

type ObjectKey struct {
// +optional
Namespace string `json:"namespace,omitempty"`
Expand Down
78 changes: 18 additions & 60 deletions api/v1alpha1/component_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var (
DowngradePolicyEnforce DowngradePolicy = "Enforce"
)

const KindComponent = "Component"

// ComponentSpec defines the desired state of Component.
type ComponentSpec struct {
// RepositoryRef is a reference to a OCMRepository.
Expand All @@ -55,6 +57,7 @@ type ComponentSpec struct {
// +kubebuilder:default:=Deny
// +optional
DowngradePolicy DowngradePolicy `json:"downgradePolicy,omitempty"`

// Semver defines the constraint of the fetched version. '>=v0.1'.
// +required
Semver string `json:"semver"`
Expand All @@ -70,18 +73,10 @@ type ComponentSpec struct {
// +optional
Verify []Verification `json:"verify,omitempty"`

// OCMConfig defines references to secrets, config maps or ocm api
// objects providing configuration data including credentials.
// +optional
SecretRefs []corev1.LocalObjectReference `json:"secretRefs,omitempty"`

// +optional
ConfigRefs []corev1.LocalObjectReference `json:"configRefs,omitempty"`

// The secrets and configs referred to by SecretRef (or SecretRefs) and Config (or ConfigRefs) may contain ocm
// config data. The ocm config allows to specify sets of configuration data
// (s. https://ocm.software/docs/cli-reference/help/configfile/). If the SecretRef (or SecretRefs) and ConfigRef and
// ConfigRefs contain ocm config sets, the user may specify which config set he wants to be effective.
// +optional
ConfigSet *string `json:"configSet"`
OCMConfig []OCMConfiguration `json:"ocmConfig,omitempty"`

// Interval at which the repository will be checked for new component
// versions.
Expand All @@ -105,10 +100,9 @@ type ComponentStatus struct {
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`

// The component controller generates an artifact which is a list of
// component descriptors. If the components were verified, other controllers
// (e.g. Resource controller) can use this without having to verify the
// signature again.
// ArtifactRef references the generated artifact containing a list of
// component descriptors. This list can be used by other controllers to
// avoid re-downloading (and potentially also re-verifying) the components.
// +optional
ArtifactRef corev1.LocalObjectReference `json:"artifactRef,omitempty"`

Expand All @@ -117,32 +111,12 @@ type ComponentStatus struct {
// reconciliation.
// +optional
Component ComponentInfo `json:"component,omitempty"`
// Propagate its effective secrets. Other controllers (e.g. Resource
// controller) may use this as default if they do not explicitly refer a
// secret.
// This is required to allow transitive defaulting (thus, e.g. Component
// defaults from OCMRepository and Resource defaults from Component) without
// having to traverse the entire chain.
// +optional
SecretRefs []corev1.LocalObjectReference `json:"secretRefs,omitempty"`

// Propagate its effective configs. Other controllers (e.g. Component or
// Resource controller) may use this as default if they do not explicitly
// refer a config.
// This is required to allow transitive defaulting (thus, e.g. Component
// defaults from OCMRepository and Resource defaults from Component) without
// having to traverse the entire chain.
// +optional
ConfigRefs []corev1.LocalObjectReference `json:"configRefs,omitempty"`

// Propagate its effective config set. Other controllers (e.g. Component or
// Resource controller) may use this as default if they do not explicitly
// specify a config set.
// This is required to allow transitive defaulting (thus, e.g. Component
// defaults from OCMRepository and Resource defaults from Component) without
// having to traverse the entire chain.

// EffectiveOCMConfig specifies the entirety of config maps and secrets
// whose configuration data was applied to the Component reconciliation,
// in the order the configuration data was applied.
// +optional
ConfigSet string `json:"configSet,omitempty"`
EffectiveOCMConfig []OCMConfiguration `json:"effectiveOCMConfig,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down Expand Up @@ -194,28 +168,12 @@ func (in Component) GetRequeueAfter() time.Duration {
return in.Spec.Interval.Duration
}

func (in *Component) GetSecretRefs() []corev1.LocalObjectReference {
return in.Spec.SecretRefs
}

func (in *Component) GetEffectiveSecretRefs() []corev1.LocalObjectReference {
return in.Status.SecretRefs
}

func (in *Component) GetConfigRefs() []corev1.LocalObjectReference {
return in.Spec.ConfigRefs
}

func (in *Component) GetEffectiveConfigRefs() []corev1.LocalObjectReference {
return in.Status.ConfigRefs
}

func (in *Component) GetConfigSet() *string {
return in.Spec.ConfigSet
func (in *Component) GetSpecifiedOCMConfig() []OCMConfiguration {
return in.Spec.OCMConfig
}

func (in *Component) GetEffectiveConfigSet() string {
return in.Status.ConfigSet
func (in *Component) GetEffectiveOCMConfig() []OCMConfiguration {
return in.Status.EffectiveOCMConfig
}

func (in *Component) GetVerifications() []Verification {
Expand Down
62 changes: 15 additions & 47 deletions api/v1alpha1/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,36 @@ package v1alpha1

import (
"github.com/fluxcd/pkg/runtime/conditions"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// SecretRefProvider are objects that provide secret refs. The interface allows all implementers to use the same
// function to retrieve its secrets.
//
// GetEffectiveSecretRefs returns references to the secrets that were effectively available for that object.
// For example, the ComponentSpec's secret ref and secret refs might be empty, but the OCMRepositorySpec of the
// OCMRepository the Component references, might have a secret ref or secret refs specified. If this is the case
// (so the ComponentSpec does not specify any secret refs but the OCMRepositorySpec does), the Component inherits
// (or defaults to) these secrets.
// For OCMRepository, GetSecretRefs() and GetEffectiveSecretRefs() would then return the same thing. For Component,
// GetSecretRefs() would return an empty list while GetEffectiveSecretRefs() would return the same thing as the
// OCMRepository's GetSecretRefs() and GetEffectiveSecretRefs().
// Each SecretRefProvider exposes its effective secrets in its status (see e.g. OCMRepository.Status). This way,
// controllers such as the Resource controller does not have to backtrack the entire kubernetes object chain to
// OCMRepository to read its defaults.
// +kubebuilder:object:generate=false
type SecretRefProvider interface {
client.Object

// GetSecretRefs return the list of all secret references specified in the spec of the implementing object.
GetSecretRefs() []corev1.LocalObjectReference

// GetEffectiveSecretRefs returns the list of all secret references specified in the spec of the implementing object.
GetEffectiveSecretRefs() []corev1.LocalObjectReference
}

// ConfigRefProvider are objects that provide secret refs. The interface allows all implementers to use the same
// function to retrieve its secrets.
//
// For a detailed explanation, see SecretRefProvider.
// ConfigRefProvider are objects that provide configurations such as credentials
// or other ocm configuration. The interface allows all implementers to use the
// same function to retrieve its configuration.
// +kubebuilder:object:generate=false
type ConfigRefProvider interface {
client.Object
GetConfigRefs() []corev1.LocalObjectReference
GetEffectiveConfigRefs() []corev1.LocalObjectReference
}

// ConfigSetProvider are objects that may contain config sets. The interface allows all implementers to use the same
// function to retrieve its config set.
//
// GetConfigSet() returns a string pointer because we have to distinguish between a purposefully set empty value and a
// unset value to determine whether to use the default.
//
// For a detailed explanation, see SecretRefProvider.
// +kubebuilder:object:generate=false
type ConfigSetProvider interface {
client.Object
GetConfigSet() *string
GetEffectiveConfigSet() string
// GetSpecifiedOCMConfig returns the configurations specifically specified
// in the spec of the ocm k8s object.
// CAREFUL: The configurations retrieved from this method might reference
// other configurable OCM objects (OCMRepository, Component, Resource,
// Replication). In that case the EffectiveOCMConfig (referencing Secrets or
// ConfigMaps) propagated by the referenced ocm k8s objects have to be
// resolved (see ocm.GetEffectiveConfig).
GetSpecifiedOCMConfig() []OCMConfiguration

// GetEffectiveOCMConfig returns the effective configurations propagated by
// the ocm k8s object.
GetEffectiveOCMConfig() []OCMConfiguration
}

// OCMK8SObject is a composite interface that the ocm-k8s-toolkit resources implement which allows them to use
// the same ocm context configuration function.
// +kubebuilder:object:generate=false
type OCMK8SObject interface {
conditions.Setter
SecretRefProvider
ConfigRefProvider
ConfigSetProvider
}

// VerificationProvider are objects that may provide verification information. The interface allows all implementers to
Expand Down
Loading

0 comments on commit 1b31e29

Please sign in to comment.