diff --git a/apis/config/v1alpha1/config_types.go b/apis/config/v1alpha1/config_types.go index 372e496c511..672358e1457 100644 --- a/apis/config/v1alpha1/config_types.go +++ b/apis/config/v1alpha1/config_types.go @@ -16,6 +16,7 @@ limitations under the License. package v1alpha1 import ( + status "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1" "github.com/open-policy-agent/gatekeeper/v3/pkg/wildcard" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -82,6 +83,7 @@ type ReadinessSpec struct { // ConfigStatus defines the observed state of Config. type ConfigStatus struct { // Important: Run "make" to regenerate code after modifying this file + ByPod []status.ConfigPodStatusStatus `json:"byPod,omitempty"` } type GVK struct { @@ -92,6 +94,8 @@ type GVK struct { // +kubebuilder:resource:scope=Namespaced // +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion // Config is the Schema for the configs API. type Config struct { diff --git a/apis/config/v1alpha1/zz_generated.deepcopy.go b/apis/config/v1alpha1/zz_generated.deepcopy.go index 75babe05f76..c60bc2cda4f 100644 --- a/apis/config/v1alpha1/zz_generated.deepcopy.go +++ b/apis/config/v1alpha1/zz_generated.deepcopy.go @@ -20,6 +20,7 @@ limitations under the License. package v1alpha1 import ( + "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1" "github.com/open-policy-agent/gatekeeper/v3/pkg/wildcard" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -30,7 +31,7 @@ func (in *Config) DeepCopyInto(out *Config) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. @@ -111,6 +112,13 @@ func (in *ConfigSpec) DeepCopy() *ConfigSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigStatus) DeepCopyInto(out *ConfigStatus) { *out = *in + if in.ByPod != nil { + in, out := &in.ByPod, &out.ByPod + *out = make([]v1beta1.ConfigPodStatusStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigStatus. diff --git a/apis/status/v1beta1/configpodstatus_types.go b/apis/status/v1beta1/configpodstatus_types.go new file mode 100644 index 00000000000..713688508ed --- /dev/null +++ b/apis/status/v1beta1/configpodstatus_types.go @@ -0,0 +1,89 @@ +package v1beta1 + +import ( + "github.com/open-policy-agent/gatekeeper/v3/pkg/operations" + "github.com/open-policy-agent/gatekeeper/v3/pkg/util" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + // "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +// ConfigPodStatusStatus defines the observed state of ConfigPodStatus. + +// +kubebuilder:object:generate=true + +type ConfigPodStatusStatus struct { + // Important: Run "make" to regenerate code after modifying this file + ID string `json:"id,omitempty"` + ConfigUID types.UID `json:"configUID,omitempty"` + Operations []string `json:"operations,omitempty"` + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + Errors []*ConfigError `json:"errors,omitempty"` +} + +// +kubebuilder:object:generate=true + +type ConfigError struct { + Type string `json:"type,omitempty"` + Message string `json:"message"` +} + +// ConfigPodStatus is the Schema for the configpodstatuses API. + +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced + +type ConfigPodStatus struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status ConfigPodStatusStatus `json:"status,omitempty"` +} + +// ConfigPodStatusList contains a list of ConfigPodStatus. + +// +kubebuilder:object:root=true +type ConfigPodStatusList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ConfigPodStatus `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ConfigPodStatus{}, &ConfigPodStatusList{}) +} + +// NewConfigStatusForPod returns an config status object +// that has been initialized with the bare minimum of fields to make it functional +// with the config status controller. +func NewConfigStatusForPod(pod *corev1.Pod, configName string, scheme *runtime.Scheme) (*ConfigPodStatus, error) { + obj := &ConfigPodStatus{} + name, err := KeyForConfig(pod.Name, configName) + if err != nil { + return nil, err + } + obj.SetName(name) + obj.SetNamespace(util.GetNamespace()) + obj.Status.ID = pod.Name + obj.Status.Operations = operations.AssignedStringList() + obj.SetLabels(map[string]string{ + ConfigNameLabel: configName, + PodLabel: pod.Name, + }) + + if err := controllerutil.SetOwnerReference(pod, obj, scheme); err != nil { + return nil, err + } + + return obj, nil +} + +// KeyForConfig returns a unique status object name given the Pod ID and +// a config object. +func KeyForConfig(id string, configName string) (string, error) { + return DashPacker(id, configName) +} diff --git a/apis/status/v1beta1/labels.go b/apis/status/v1beta1/labels.go index 0f0caca91ce..61f3a7f384f 100644 --- a/apis/status/v1beta1/labels.go +++ b/apis/status/v1beta1/labels.go @@ -2,6 +2,7 @@ package v1beta1 // Label keys used for internal gatekeeper operations. const ( + ConfigNameLabel = "internal.gatekeeper.sh/config-name" ExpansionTemplateNameLabel = "internal.gatekeeper.sh/expansiontemplate-name" ConstraintNameLabel = "internal.gatekeeper.sh/constraint-name" ConstraintKindLabel = "internal.gatekeeper.sh/constraint-kind" diff --git a/apis/status/v1beta1/zz_generated.deepcopy.go b/apis/status/v1beta1/zz_generated.deepcopy.go index c361b6cdd9a..fa401e6ced1 100644 --- a/apis/status/v1beta1/zz_generated.deepcopy.go +++ b/apis/status/v1beta1/zz_generated.deepcopy.go @@ -24,6 +24,110 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigError) DeepCopyInto(out *ConfigError) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigError. +func (in *ConfigError) DeepCopy() *ConfigError { + if in == nil { + return nil + } + out := new(ConfigError) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigPodStatus) DeepCopyInto(out *ConfigPodStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigPodStatus. +func (in *ConfigPodStatus) DeepCopy() *ConfigPodStatus { + if in == nil { + return nil + } + out := new(ConfigPodStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ConfigPodStatus) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigPodStatusList) DeepCopyInto(out *ConfigPodStatusList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ConfigPodStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigPodStatusList. +func (in *ConfigPodStatusList) DeepCopy() *ConfigPodStatusList { + if in == nil { + return nil + } + out := new(ConfigPodStatusList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ConfigPodStatusList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigPodStatusStatus) DeepCopyInto(out *ConfigPodStatusStatus) { + *out = *in + if in.Operations != nil { + in, out := &in.Operations, &out.Operations + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Errors != nil { + in, out := &in.Errors, &out.Errors + *out = make([]*ConfigError, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(ConfigError) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigPodStatusStatus. +func (in *ConfigPodStatusStatus) DeepCopy() *ConfigPodStatusStatus { + if in == nil { + return nil + } + out := new(ConfigPodStatusStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConstraintPodStatus) DeepCopyInto(out *ConstraintPodStatus) { *out = *in diff --git a/config/crd/bases/config.gatekeeper.sh_configs.yaml b/config/crd/bases/config.gatekeeper.sh_configs.yaml index ddd2f55394f..2bed80a7eb0 100644 --- a/config/crd/bases/config.gatekeeper.sh_configs.yaml +++ b/config/crd/bases/config.gatekeeper.sh_configs.yaml @@ -112,7 +112,43 @@ spec: type: object status: description: ConfigStatus defines the observed state of Config. + properties: + byPod: + items: + properties: + configUID: + description: |- + UID is a type that holds unique ID values, including UUIDs. Because we + don't ONLY use UUIDs, this is an alias to string. Being a type captures + intent and helps make sure that UIDs and names do not get conflated. + type: string + errors: + items: + properties: + message: + type: string + type: + type: string + required: + - message + type: object + type: array + id: + description: 'Important: Run "make" to regenerate code after + modifying this file' + type: string + observedGeneration: + format: int64 + type: integer + operations: + items: + type: string + type: array + type: object + type: array type: object type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/bases/status.gatekeeper.sh_configpodstatuses.yaml b/config/crd/bases/status.gatekeeper.sh_configpodstatuses.yaml new file mode 100644 index 00000000000..57604c6083e --- /dev/null +++ b/config/crd/bases/status.gatekeeper.sh_configpodstatuses.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: configpodstatuses.status.gatekeeper.sh +spec: + group: status.gatekeeper.sh + names: + kind: ConfigPodStatus + listKind: ConfigPodStatusList + plural: configpodstatuses + singular: configpodstatus + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + status: + properties: + configUID: + description: |- + UID is a type that holds unique ID values, including UUIDs. Because we + don't ONLY use UUIDs, this is an alias to string. Being a type captures + intent and helps make sure that UIDs and names do not get conflated. + type: string + errors: + items: + properties: + message: + type: string + type: + type: string + required: + - message + type: object + type: array + id: + description: 'Important: Run "make" to regenerate code after modifying + this file' + type: string + observedGeneration: + format: int64 + type: integer + operations: + items: + type: string + type: array + type: object + type: object + served: true + storage: true diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 4eb253c7672..568b63293b9 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -8,6 +8,7 @@ resources: - bases/status.gatekeeper.sh_constrainttemplatepodstatuses.yaml - bases/status.gatekeeper.sh_mutatorpodstatuses.yaml - bases/status.gatekeeper.sh_expansiontemplatepodstatuses.yaml +- bases/status.gatekeeper.sh_configpodstatuses.yaml - bases/mutations.gatekeeper.sh_assign.yaml - bases/mutations.gatekeeper.sh_assignimage.yaml - bases/mutations.gatekeeper.sh_assignmetadata.yaml diff --git a/manifest_staging/charts/gatekeeper/crds/config-customresourcedefinition.yaml b/manifest_staging/charts/gatekeeper/crds/config-customresourcedefinition.yaml index 11a5d922789..5182e6625a2 100644 --- a/manifest_staging/charts/gatekeeper/crds/config-customresourcedefinition.yaml +++ b/manifest_staging/charts/gatekeeper/crds/config-customresourcedefinition.yaml @@ -112,7 +112,42 @@ spec: type: object status: description: ConfigStatus defines the observed state of Config. + properties: + byPod: + items: + properties: + configUID: + description: |- + UID is a type that holds unique ID values, including UUIDs. Because we + don't ONLY use UUIDs, this is an alias to string. Being a type captures + intent and helps make sure that UIDs and names do not get conflated. + type: string + errors: + items: + properties: + message: + type: string + type: + type: string + required: + - message + type: object + type: array + id: + description: 'Important: Run "make" to regenerate code after modifying this file' + type: string + observedGeneration: + format: int64 + type: integer + operations: + items: + type: string + type: array + type: object + type: array type: object type: object served: true storage: true + subresources: + status: {} diff --git a/manifest_staging/deploy/gatekeeper.yaml b/manifest_staging/deploy/gatekeeper.yaml index fe375e4eb43..a868bc5df07 100644 --- a/manifest_staging/deploy/gatekeeper.yaml +++ b/manifest_staging/deploy/gatekeeper.yaml @@ -2498,10 +2498,45 @@ spec: type: object status: description: ConfigStatus defines the observed state of Config. + properties: + byPod: + items: + properties: + configUID: + description: |- + UID is a type that holds unique ID values, including UUIDs. Because we + don't ONLY use UUIDs, this is an alias to string. Being a type captures + intent and helps make sure that UIDs and names do not get conflated. + type: string + errors: + items: + properties: + message: + type: string + type: + type: string + required: + - message + type: object + type: array + id: + description: 'Important: Run "make" to regenerate code after modifying this file' + type: string + observedGeneration: + format: int64 + type: integer + operations: + items: + type: string + type: array + type: object + type: array type: object type: object served: true storage: true + subresources: + status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition