Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement config pod status #3544

Merged
merged 30 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dfe3878
add config pod status crd
Sep 14, 2024
14d80aa
generate manifests
Sep 16, 2024
369004c
implement config status controller wip
Sep 16, 2024
9c27e83
implement config pod status logic
Sep 17, 2024
290b46e
remove make comment from api docs
Sep 17, 2024
2d6ccba
fix go lint errors
Sep 17, 2024
b149d3f
fix helm charts
Sep 17, 2024
bc5ba07
fix double import
Sep 17, 2024
8806502
add or delete pod status at the end
Sep 18, 2024
a2f6e9e
pass request.name as key when config is deleted
Sep 18, 2024
9cf8fe5
update config controller to pass request.NameSpace.Name
Sep 18, 2024
00c3e41
wrap fake client with mutex logic to resolve data race issues
Sep 19, 2024
842b26a
use wrapped fake client in failing test
Sep 19, 2024
9d05fc2
fix typo in retry count
Sep 19, 2024
5f220bb
fix config by pod status not updating issue
Sep 20, 2024
0f431eb
Address review comments
Sep 20, 2024
79c048b
fix lint errors
Sep 20, 2024
9c5b5d7
add unit tests for config pod status types
Sep 20, 2024
3a4e7b2
write upsert error to status obj
Sep 21, 2024
1d44b5f
update kubebuilder tag in config status controller
Sep 23, 2024
f371fb3
pass namespace to reconcile request of config controller
Sep 23, 2024
45c2da7
address review comments
Sep 23, 2024
4dae25f
use namespace stored in config pod status
Sep 24, 2024
b326059
store namespace in configpod status name
Sep 24, 2024
b75a3ea
address review comments
Sep 25, 2024
8201cff
wrap fake client with mutex in unit tests
Oct 1, 2024
958be2c
fix expansion template status to use self only and gate all status co…
Oct 1, 2024
a860f6c
remove gating in mutator status controller
Oct 2, 2024
3600f97
Merge branch 'master' into add_status_to_config
ritazh Oct 4, 2024
20cb2ca
Merge branch 'master' into add_status_to_config
ritazh Oct 10, 2024
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
4 changes: 4 additions & 0 deletions apis/config/v1alpha1/config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
10 changes: 9 additions & 1 deletion apis/config/v1alpha1/zz_generated.deepcopy.go

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

94 changes: 94 additions & 0 deletions apis/status/v1beta1/configpodstatus_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
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/types"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// ConfigPodStatusStatus defines the observed state of ConfigPodStatus.

// +kubebuilder:object:generate=true

type ConfigPodStatusStatus struct {
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, configNamespace string, configName string, scheme *runtime.Scheme) (*ConfigPodStatus, error) {
obj := &ConfigPodStatus{}
name, err := KeyForConfig(pod.Name, configNamespace, 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.
// The object name must satisfy RFC 1123 Label Names spec
// (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/)
// and Kubernetes validation rules for object names.
//
// It's possible that dash packing/unpacking would result in a name
// that exceeds the maximum length allowed, but for Config resources,
// the configName should always be "config", and namespace would be "gatekeeper-system",
// so this validation will hold.
func KeyForConfig(id string, configNamespace string, configName string) (string, error) {
abhipatnala marked this conversation as resolved.
Show resolved Hide resolved
return DashPacker(id, configNamespace, configName)
}
69 changes: 69 additions & 0 deletions apis/status/v1beta1/configpodstatus_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package v1beta1_test

import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1"
"github.com/open-policy-agent/gatekeeper/v3/pkg/fakes"
"github.com/open-policy-agent/gatekeeper/v3/pkg/operations"
"github.com/open-policy-agent/gatekeeper/v3/test/testutils"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

func TestNewConfigStatusForPod(t *testing.T) {
const podName = "some-gk-pod"
const podNS = "a-gk-namespace"
const configName = "a-config"
const configNameSpace = "a-gk-ns"

testutils.Setenv(t, "POD_NAMESPACE", podNS)

scheme := runtime.NewScheme()
err := v1beta1.AddToScheme(scheme)
if err != nil {
t.Fatal(err)
}

err = corev1.AddToScheme(scheme)
if err != nil {
t.Fatal(err)
}

pod := fakes.Pod(
fakes.WithNamespace(podNS),
fakes.WithName(podName),
)

expectedStatus := &v1beta1.ConfigPodStatus{}
expectedStatus.SetName("some--gk--pod-a--gk--ns-a--config")
expectedStatus.SetNamespace(podNS)
expectedStatus.Status.ID = podName
expectedStatus.Status.Operations = operations.AssignedStringList()
expectedStatus.SetLabels(map[string]string{
v1beta1.ConfigNameLabel: configName,
v1beta1.PodLabel: podName,
})

err = controllerutil.SetOwnerReference(pod, expectedStatus, scheme)
if err != nil {
t.Fatal(err)
}

status, err := v1beta1.NewConfigStatusForPod(pod, configNameSpace, configName, scheme)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(expectedStatus, status); diff != "" {
t.Fatal(diff)
}
n, err := v1beta1.KeyForConfig(podName, configNameSpace, configName)
if err != nil {
t.Fatal(err)
}
if status.Name != n {
t.Fatal("got status.Name != n, want equal")
}
}
1 change: 1 addition & 0 deletions apis/status/v1beta1/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
104 changes: 104 additions & 0 deletions apis/status/v1beta1/zz_generated.deepcopy.go

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

6 changes: 6 additions & 0 deletions cmd/build/helmify/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ patchesJson6902:
kind: CustomResourceDefinition
name: expansiontemplatepodstatuses.status.gatekeeper.sh
path: labels_patch.yaml
- target:
group: apiextensions.k8s.io
version: v1
kind: CustomResourceDefinition
name: configpodstatuses.status.gatekeeper.sh
path: labels_patch.yaml
- target:
group: apiextensions.k8s.io
version: v1
Expand Down
34 changes: 34 additions & 0 deletions config/crd/bases/config.gatekeeper.sh_configs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,41 @@ 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:
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: {}
Loading
Loading