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

[CECO-570] Add operator introspection #817

Merged
merged 24 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2311579
Add operator introspection
khewonc Jun 7, 2023
07331db
Send reconcile request when provider added or deleted
khewonc Jun 22, 2023
e82b27f
Merge branch 'main' into khewonc/introspection
khewonc Aug 14, 2023
49877c1
Merge branch 'main' into khewonc/introspection
khewonc Sep 6, 2023
12e7092
introspection v2
khewonc Sep 6, 2023
a0fb702
Merge branch 'main' into khewonc/introspection
khewonc Sep 11, 2023
6e632a2
Change local agent service selector
khewonc Sep 11, 2023
1f1403f
Merge branch 'main' into khewonc/introspection
khewonc Oct 11, 2023
01def37
Suggestions from code review
khewonc Oct 11, 2023
be66ae2
Cleanup unused options
khewonc Oct 11, 2023
c6382de
Simplify providers struct
khewonc Oct 23, 2023
6e6d537
Merge branch 'main' into khewonc/introspection
khewonc Oct 24, 2023
70219e1
Fix stale status
khewonc Nov 7, 2023
cbaa0f0
Merge branch 'main' into khewonc/introspection
khewonc Nov 7, 2023
dd28d7f
Update after merging main
khewonc Nov 7, 2023
3bf8002
[CECO-754][introspection] Clean up unused ds/eds (#1014)
khewonc Dec 21, 2023
d4723ef
[CECO-755][introspection] Limit provider values using allowlist (#1021)
khewonc Dec 22, 2023
d5989da
[CECO-849][introspection] Remove unused ds status (#1023)
khewonc Dec 29, 2023
bade2df
Review suggestions
khewonc Jan 2, 2024
3bb1ccb
Merge branch 'main' into khewonc/introspection
khewonc Jan 2, 2024
9cb824f
Fix capitalisation in types
khewonc Jan 2, 2024
3975dfc
[introspection] Add flag, fix types, override name (#1035)
khewonc Jan 9, 2024
c369113
Merge branch 'main' into khewonc/introspection
khewonc Jan 9, 2024
553d24b
Adding LegacyProvider label to daemonset if introspection is disabled
Jan 11, 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
5 changes: 4 additions & 1 deletion controllers/datadogagent/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type Reconciler struct {
client client.Client
versionInfo *version.Info
platformInfo kubernetes.PlatformInfo
profiles *kubernetes.Profiles
scheme *runtime.Scheme
log logr.Logger
recorder record.EventRecorder
Expand All @@ -83,12 +84,14 @@ type Reconciler struct {

// NewReconciler returns a reconciler for DatadogAgent
func NewReconciler(options ReconcilerOptions, client client.Client, versionInfo *version.Info, platformInfo kubernetes.PlatformInfo,
scheme *runtime.Scheme, log logr.Logger, recorder record.EventRecorder, metricForwarder datadog.MetricForwardersManager) (*Reconciler, error) {
profiles *kubernetes.Profiles, scheme *runtime.Scheme, log logr.Logger, recorder record.EventRecorder,
metricForwarder datadog.MetricForwardersManager) (*Reconciler, error) {
return &Reconciler{
options: options,
client: client,
versionInfo: versionInfo,
platformInfo: platformInfo,
profiles: profiles,
scheme: scheme,
log: log,
recorder: recorder,
Expand Down
69 changes: 67 additions & 2 deletions controllers/datadogagent/controller_reconcile_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package datadogagent

import (
"context"
"fmt"
"time"

"github.com/DataDog/datadog-operator/apis/datadoghq/common/v1"
Expand All @@ -16,6 +17,7 @@ import (
"github.com/DataDog/datadog-operator/controllers/datadogagent/feature"
"github.com/DataDog/datadog-operator/controllers/datadogagent/override"
"github.com/DataDog/datadog-operator/pkg/controller/utils/datadog"
"github.com/DataDog/datadog-operator/pkg/kubernetes"

edsv1alpha1 "github.com/DataDog/extendeddaemonset/api/v1alpha1"
"github.com/go-logr/logr"
Expand All @@ -31,6 +33,7 @@ func (r *Reconciler) reconcileV2Agent(logger logr.Logger, requiredComponents fea
var eds *edsv1alpha1.ExtendedDaemonSet
var daemonset *appsv1.DaemonSet
var podManagers feature.PodTemplateManagers
var err error

daemonsetLogger := logger.WithValues("component", datadoghqv2alpha1.NodeAgentComponentName)

Expand Down Expand Up @@ -78,7 +81,38 @@ func (r *Reconciler) reconcileV2Agent(logger logr.Logger, requiredComponents fea
}
return r.cleanupV2ExtendedDaemonSet(daemonsetLogger, dda, eds, newStatus)
}
return r.createOrUpdateExtendedDaemonset(daemonsetLogger, dda, eds, newStatus, updateEDSStatusV2WithAgent)

providersList := r.profiles.GetProviders()
switch {
case len(*providersList) == 1:
for provider := range *providersList {
eds.Spec.Template = *override.Provider(&eds.Spec.Template, provider, features)
return r.createOrUpdateExtendedDaemonset(daemonsetLogger, dda, eds, newStatus, updateEDSStatusV2WithAgent)
}
case len(*providersList) > 1:
var e error
for p := range *providersList {
edsCopy := eds.DeepCopy()
podTemplate := edsCopy.Spec.Template
edsCopy.Spec.Template = *override.Provider(&podTemplate, p, features)

// use provider-specific name
edsCopy.Name = fmt.Sprintf("%s-%s", edsCopy.Name, p.ComponentName)
// add provider-specific node selector
nodeSelector := kubernetes.GenerateNodeSelector(p)
edsCopy.Spec.Template.Spec.NodeSelector = nodeSelector

result, e = r.createOrUpdateExtendedDaemonset(daemonsetLogger, dda, edsCopy, newStatus, updateEDSStatusV2WithAgent)
if e != nil {
return result, e
}
}
return result, e
default:
return r.createOrUpdateExtendedDaemonset(daemonsetLogger, dda, eds, newStatus, updateEDSStatusV2WithAgent)
}

return reconcile.Result{}, err
}

// Start by creating the Default Agent daemonset
Expand Down Expand Up @@ -118,7 +152,38 @@ func (r *Reconciler) reconcileV2Agent(logger logr.Logger, requiredComponents fea
}
return r.cleanupV2DaemonSet(daemonsetLogger, dda, daemonset, newStatus)
}
return r.createOrUpdateDaemonset(daemonsetLogger, dda, daemonset, newStatus, updateDSStatusV2WithAgent)

providersList := r.profiles.GetProviders()
switch {
case len(*providersList) == 1:
for provider := range *providersList {
daemonset.Spec.Template = *override.Provider(&daemonset.Spec.Template, provider, features)
return r.createOrUpdateDaemonset(daemonsetLogger, dda, daemonset, newStatus, updateDSStatusV2WithAgent)
}
case len(*providersList) > 1:
var e error
for p := range *providersList {
dsCopy := daemonset.DeepCopy()
podTemplate := dsCopy.Spec.Template
dsCopy.Spec.Template = *override.Provider(&podTemplate, p, features)

// use provider-specific name
dsCopy.Name = fmt.Sprintf("%s-%s", dsCopy.Name, p.ComponentName)
// add provider-specific node selector
nodeSelector := kubernetes.GenerateNodeSelector(p)
dsCopy.Spec.Template.Spec.NodeSelector = nodeSelector

result, e = r.createOrUpdateDaemonset(daemonsetLogger, dda, dsCopy, newStatus, updateDSStatusV2WithAgent)
if e != nil {
return result, e
}
}
return result, e
default:
return r.createOrUpdateDaemonset(daemonsetLogger, dda, daemonset, newStatus, updateDSStatusV2WithAgent)
}

return reconcile.Result{}, err
}

func updateDSStatusV2WithAgent(dda *appsv1.DaemonSet, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string) {
Expand Down
11 changes: 11 additions & 0 deletions controllers/datadogagent/merger/fake/volume_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,14 @@ func NewFakeVolumeManager(t testing.TB) *VolumeManager {
t: t,
}
}

// RemoveVolume provides a mock function with given fields: volume
func (_m *VolumeManager) RemoveVolume(volume string) {
for id, cVolume := range _m.Volumes {
if volume == cVolume.Name {
updatedVolumes := make([]*v1.Volume, 0, len(_m.Volumes)-1)
updatedVolumes = append(updatedVolumes, _m.Volumes[:id]...)
_m.Volumes = append(updatedVolumes, _m.Volumes[id+1:]...)
}
}
}
11 changes: 11 additions & 0 deletions controllers/datadogagent/merger/fake/volume_mount_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ func (_m *VolumeMountManager) AddVolumeMountToContainerWithMergeFunc(volumeMount
return _m.volumeMountMerge(containerName, volumeMount, volumeMountMergeFunc)
}

// RemoveVolumeMount provides a mock function with given fields: volumeMount
func (_m *VolumeMountManager) RemoveVolumeMount(volumeMount string) {
for id, v := range _m.VolumeMountsByC[AllContainers] {
if v.Name == volumeMount {
updatedVolumeMounts := make([]*v1.VolumeMount, 0, len(_m.VolumeMountsByC[AllContainers])-1)
updatedVolumeMounts = append(updatedVolumeMounts, _m.VolumeMountsByC[AllContainers][:id]...)
_m.VolumeMountsByC[AllContainers] = append(updatedVolumeMounts, _m.VolumeMountsByC[AllContainers][id+1:]...)
}
}
}

func (_m *VolumeMountManager) volumeMountMerge(containerName commonv1.AgentContainerName, volume *v1.VolumeMount, volumeMergeFunc merger.VolumeMountMergeFunction) error {
found := false
idFound := 0
Expand Down
13 changes: 13 additions & 0 deletions controllers/datadogagent/merger/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type VolumeManager interface {
// Add the volume to the PodTemplate.
// Provide merge functions if the merge is specific.
AddVolumeWithMergeFunc(volume *corev1.Volume, volumeMergeFunc VolumeMergeFunction) error
// RemoveVolume removes a volume from the PodTemplate.
RemoveVolume(volume string)
}

// NewVolumeManager returns a new instance of the VolumeManager
Expand Down Expand Up @@ -146,3 +148,14 @@ func mergeMode(a, b *int32) *int32 {
}
return a
}

// RemoveVolume removes a volume from the PodTemplate
func (impl *volumeManagerImpl) RemoveVolume(volume string) {
khewonc marked this conversation as resolved.
Show resolved Hide resolved
for id, cVolume := range impl.podTmpl.Spec.Volumes {
if volume == cVolume.Name {
updatedVolumes := make([]corev1.Volume, 0, len(impl.podTmpl.Spec.Volumes)-1)
updatedVolumes = append(updatedVolumes, impl.podTmpl.Spec.Volumes[:id]...)
impl.podTmpl.Spec.Volumes = append(updatedVolumes, impl.podTmpl.Spec.Volumes[id+1:]...)
}
}
}
20 changes: 20 additions & 0 deletions controllers/datadogagent/merger/volume_mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type VolumeMountManager interface {
// Add the volumeMount to the container matching the containerName.
// Provide merge functions if the merge is specific.
AddVolumeMountToContainerWithMergeFunc(volumeMount *corev1.VolumeMount, containerName commonv1.AgentContainerName, volumeMountMergeFunc VolumeMountMergeFunction) error
// Remove the volumeMount from all containers of the PodTemplate.
RemoveVolumeMount(volumeMount string)
}

// NewVolumeMountManager returns a new instance of the VolumeMountManager
Expand Down Expand Up @@ -128,3 +130,21 @@ func IgnoreNewVolumeMountMergeFunction(current, newVolumeMount *corev1.VolumeMou
func ErrorOnMergeAttemptdVolumeMountMergeFunction(current, newVolumeMount *corev1.VolumeMount) (*corev1.VolumeMount, error) {
return nil, errMergeAttempted
}

// RemoveVolumeMount removes a volumeMount from all containers of the PodTemplate
func (impl *volumeMountManagerImpl) RemoveVolumeMount(volumeMount string) {
for id := range impl.podTmpl.Spec.Containers {
RemoveVolumeMountFromContainer(&impl.podTmpl.Spec.Containers[id], volumeMount)
}
}

// RemoveVolumeMountFromContainer removes a volumeMount from a specific container
func RemoveVolumeMountFromContainer(container *corev1.Container, volumeMount string) {
for id, cVolumeMount := range container.VolumeMounts {
if volumeMount == cVolumeMount.Name {
updatedVolumeMounts := make([]corev1.VolumeMount, 0, len(container.VolumeMounts)-1)
updatedVolumeMounts = append(updatedVolumeMounts, container.VolumeMounts[:id]...)
container.VolumeMounts = append(updatedVolumeMounts, container.VolumeMounts[id+1:]...)
}
}
}
71 changes: 71 additions & 0 deletions controllers/datadogagent/merger/volume_mount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,74 @@ func TestAddVolumeMountToContainer(t *testing.T) {
})
}
}

func TestRemoveVolumeMountFromContainer(t *testing.T) {
volumemountFoo := &corev1.VolumeMount{
Name: "foo",
MountPath: "/path/foo",
}
volumemountFoo2 := &corev1.VolumeMount{
Name: "foo2",
MountPath: "/path/foo2",
}
volumemountBar := &corev1.VolumeMount{
Name: "bar",
MountPath: "/path/bar",
}
type args struct {
container *corev1.Container
volumemount string
}
tests := []struct {
name string
args args
want []corev1.VolumeMount
}{
{
name: "container.volumeMount is empty",
args: args{
container: &corev1.Container{},
volumemount: "foo",
},
want: nil,
},
{
name: "one existing volumemount",
args: args{
container: &corev1.Container{
VolumeMounts: []corev1.VolumeMount{*volumemountFoo},
},
volumemount: "foo",
},
want: []corev1.VolumeMount{},
},
{
name: "multiple existing volumemounts",
args: args{
container: &corev1.Container{
VolumeMounts: []corev1.VolumeMount{*volumemountFoo, *volumemountFoo2, *volumemountBar},
},
volumemount: "foo2",
},
want: []corev1.VolumeMount{*volumemountFoo, *volumemountBar},
},
{
name: "remove nonexistent volumemounts",
args: args{
container: &corev1.Container{
VolumeMounts: []corev1.VolumeMount{*volumemountFoo, *volumemountFoo2, *volumemountBar},
},
volumemount: "bar2",
},
want: []corev1.VolumeMount{*volumemountFoo, *volumemountFoo2, *volumemountBar},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RemoveVolumeMountFromContainer(tt.args.container, tt.args.volumemount)
if !reflect.DeepEqual(tt.args.container.VolumeMounts, tt.want) {
t.Errorf("RemoveVolumeMountFromContainer() = %v, want %v", tt.args.container.VolumeMounts, tt.want)
}
})
}
}
Loading