Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/go_modules/internal/tools/golang.…
Browse files Browse the repository at this point in the history
…org/x/tools-0.30.0
  • Loading branch information
a-thaler authored Feb 12, 2025
2 parents d1972af + b885c89 commit bec97a2
Show file tree
Hide file tree
Showing 6 changed files with 406 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ENV_GARDENER_MIN_NODES=1
ENV_GARDENER_MAX_NODES=2

## Dependencies
ENV_ISTIO_VERSION=1.14.0
ENV_ISTIO_VERSION=1.14.1
ENV_GORELEASER_VERSION=v1.23.0

## Default Docker Images
Expand Down
2 changes: 1 addition & 1 deletion docs/contributor/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Telemetry Manager has been bootstrapped with [Kubebuilder](https://github.com/ku

- Install [kubebuilder 3.6.0](https://github.com/kubernetes-sigs/kubebuilder), which is the base framework for Telemetry Manager. Required to add new APIs.
- Install [Golang 1.20](https://golang.org/dl/) or newer (for development and local execution).
- Install [Docker](https://www.docker.com/get-started).
- Install [Docker](https://www.docker.com/get-started/).
- Install [golangci-lint](https://golangci-lint.run).
- Install [ginkgo CLI](https://pkg.go.dev/github.com/onsi/ginkgo/ginkgo) to run the E2E test commands straight from your terminal.

Expand Down
22 changes: 22 additions & 0 deletions internal/reconciler/logpipeline/otel/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ func (r *Reconciler) doReconcile(ctx context.Context, pipeline *telemetryv1alpha
return fmt.Errorf("failed to fetch deployable log pipelines: %w", err)
}

var reconcilablePipelinesRequiringAgents = r.getPipelinesRequiringAgents(reconcilablePipelines)

if len(reconcilablePipelinesRequiringAgents) == 0 {
logf.FromContext(ctx).V(1).Info("cleaning up log agent resources: no log pipelines require an agent")

if err = r.agentApplierDeleter.DeleteResources(ctx, r.Client); err != nil {
return fmt.Errorf("failed to delete agent resources: %w", err)
}
}

if len(reconcilablePipelines) == 0 {
logf.FromContext(ctx).V(1).Info("cleaning up log pipeline resources: all log pipelines are non-reconcilable")

Expand Down Expand Up @@ -317,6 +327,18 @@ func getAgentPorts() []int32 {
}
}

func (r *Reconciler) getPipelinesRequiringAgents(allPipelines []telemetryv1alpha1.LogPipeline) []telemetryv1alpha1.LogPipeline {
var pipelinesRequiringAgents []telemetryv1alpha1.LogPipeline

for i := range allPipelines {
if isLogAgentRequired(&allPipelines[i]) {
pipelinesRequiringAgents = append(pipelinesRequiringAgents, allPipelines[i])
}
}

return pipelinesRequiringAgents
}

func isLogAgentRequired(pipeline *telemetryv1alpha1.LogPipeline) bool {
input := pipeline.Spec.Input

Expand Down
215 changes: 212 additions & 3 deletions internal/reconciler/logpipeline/otel/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestReconcile(t *testing.T) {
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline).WithStatusSubresource(&pipeline).Build()

agentApplierDeleterMock := &mocks.AgentApplierDeleter{}
agentApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil)
agentApplierDeleterMock.On("DeleteResources", mock.Anything, mock.Anything).Return(nil).Times(1)

agentConfigBuilderMock := &mocks.AgentConfigBuilder{}
agentConfigBuilderMock.On("Build", mock.Anything).Return(&gateway.Config{}, nil, nil).Times(1)
Expand Down Expand Up @@ -97,7 +97,7 @@ func TestReconcile(t *testing.T) {
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline).WithStatusSubresource(&pipeline).Build()

agentApplierDeleterMock := &mocks.AgentApplierDeleter{}
agentApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil)
agentApplierDeleterMock.On("DeleteResources", mock.Anything, mock.Anything).Return(nil).Times(1)

agentConfigBuilderMock := &mocks.AgentConfigBuilder{}
agentConfigBuilderMock.On("Build", containsPipeline(pipeline), mock.Anything).Return(&gateway.Config{}, nil, nil).Times(1)
Expand Down Expand Up @@ -150,7 +150,7 @@ func TestReconcile(t *testing.T) {
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline).WithStatusSubresource(&pipeline).Build()

agentApplierDeleterMock := &mocks.AgentApplierDeleter{}
agentApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil)
agentApplierDeleterMock.On("DeleteResources", mock.Anything, mock.Anything).Return(nil).Times(1)

agentConfigBuilderMock := &mocks.AgentConfigBuilder{}
agentConfigBuilderMock.On("Build", containsPipeline(pipeline), mock.Anything).Return(&gateway.Config{}, nil, nil).Times(1)
Expand Down Expand Up @@ -196,6 +196,7 @@ func TestReconcile(t *testing.T) {

gatewayConfigBuilderMock.AssertExpectations(t)
})

t.Run("log agent daemonset is not ready", func(t *testing.T) {
pipeline := testutils.NewLogPipelineBuilder().WithName("pipeline").WithOTLPOutput().WithApplicationInput(true).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline).WithStatusSubresource(&pipeline).Build()
Expand Down Expand Up @@ -299,12 +300,199 @@ func TestReconcile(t *testing.T) {
agentConfigBuilderMock.AssertExpectations(t)
gatewayConfigBuilderMock.AssertExpectations(t)
})

// TODO: "referenced secret missing" (requires SecretRefValidator to be implemented)
// TODO: "referenced secret exists" (requires SecretRefValidator to be implemented)
// TODO: "flow healthy" (requires SelfMonitoring to be implemented)
// TODO: "tls conditions" (requires TLSCertValidator to be implemented)
// TODO: "all log pipelines are non-reconcilable" (requires SecretRefValidator to be implemented)
// TODO: "Check different Pod Error Conditions" (requires SecretRefValidator to be implemented)

t.Run("one log pipeline does not require an agent", func(t *testing.T) {
pipeline := testutils.NewLogPipelineBuilder().WithName("pipeline").WithOTLPOutput().WithApplicationInput(false).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline).WithStatusSubresource(&pipeline).Build()

agentApplierDeleterMock := &mocks.AgentApplierDeleter{}
agentApplierDeleterMock.On("DeleteResources", mock.Anything, mock.Anything).Return(nil).Times(1)

gatewayConfigBuilderMock := &mocks.GatewayConfigBuilder{}
gatewayConfigBuilderMock.On("Build", mock.Anything, containsPipeline(pipeline), mock.Anything).Return(&gateway.Config{}, nil, nil).Times(1)

gatewayApplierDeleterMock := &mocks.GatewayApplierDeleter{}
gatewayApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil)

gatewayProberStub := commonStatusStubs.NewDeploymentSetProber(nil)
agentProberStub := commonStatusStubs.NewDaemonSetProber(nil)

sut := New(
fakeClient,
telemetryNamespace,
moduleVersion,
&mocks.AgentConfigBuilder{},
agentApplierDeleterMock,
agentProberStub,
gatewayApplierDeleterMock,
gatewayConfigBuilderMock,
gatewayProberStub,
istioStatusCheckerStub,
&Validator{},
&conditions.ErrorToMessageConverter{})
err := sut.Reconcile(context.Background(), &pipeline)
require.NoError(t, err)

var updatedPipeline telemetryv1alpha1.LogPipeline
_ = fakeClient.Get(context.Background(), types.NamespacedName{Name: pipeline.Name}, &updatedPipeline)

requireHasStatusCondition(t, updatedPipeline,
conditions.TypeAgentHealthy,
metav1.ConditionTrue,
conditions.ReasonLogAgentNotRequired,
"")

agentApplierDeleterMock.AssertExpectations(t)
gatewayConfigBuilderMock.AssertExpectations(t)
})

t.Run("some log pipelines do not require an agent", func(t *testing.T) {
pipeline1 := testutils.NewLogPipelineBuilder().WithName("pipeline1").WithOTLPOutput().WithApplicationInput(false).Build()
pipeline2 := testutils.NewLogPipelineBuilder().WithName("pipeline2").WithOTLPOutput().WithApplicationInput(true).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline1, &pipeline2).WithStatusSubresource(&pipeline1, &pipeline2).Build()

agentConfigBuilderMock := &mocks.AgentConfigBuilder{}
agentConfigBuilderMock.On("Build", containsPipelines([]telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}), mock.Anything).Return(&agent.Config{}, nil, nil).Times(1)

agentApplierDeleterMock := &mocks.AgentApplierDeleter{}
agentApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil).Times(1)

gatewayConfigBuilderMock := &mocks.GatewayConfigBuilder{}
gatewayConfigBuilderMock.On("Build", mock.Anything, containsPipelines([]telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}), mock.Anything).Return(&gateway.Config{}, nil, nil)

gatewayApplierDeleterMock := &mocks.GatewayApplierDeleter{}
gatewayApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil)

gatewayProberStub := commonStatusStubs.NewDeploymentSetProber(nil)
agentProberStub := commonStatusStubs.NewDaemonSetProber(nil)

sut := New(
fakeClient,
telemetryNamespace,
moduleVersion,
agentConfigBuilderMock,
agentApplierDeleterMock,
agentProberStub,
gatewayApplierDeleterMock,
gatewayConfigBuilderMock,
gatewayProberStub,
istioStatusCheckerStub,
&Validator{},
&conditions.ErrorToMessageConverter{})
err1 := sut.Reconcile(context.Background(), &pipeline1)
err2 := sut.Reconcile(context.Background(), &pipeline2)

require.NoError(t, err1)
require.NoError(t, err2)

var updatedPipeline1 telemetryv1alpha1.LogPipeline
_ = fakeClient.Get(context.Background(), types.NamespacedName{Name: pipeline1.Name}, &updatedPipeline1)

requireHasStatusCondition(t, updatedPipeline1,
conditions.TypeAgentHealthy,
metav1.ConditionTrue,
conditions.ReasonLogAgentNotRequired,
"")

agentConfigBuilderMock.AssertExpectations(t)
agentApplierDeleterMock.AssertExpectations(t)
gatewayConfigBuilderMock.AssertExpectations(t)
})

t.Run("all log pipelines do not require an agent", func(t *testing.T) {
pipeline1 := testutils.NewLogPipelineBuilder().WithName("pipeline1").WithOTLPOutput().WithApplicationInput(false).Build()
pipeline2 := testutils.NewLogPipelineBuilder().WithName("pipeline2").WithOTLPOutput().WithApplicationInput(false).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&pipeline1, &pipeline2).WithStatusSubresource(&pipeline1, &pipeline2).Build()

agentApplierDeleterMock := &mocks.AgentApplierDeleter{}
agentApplierDeleterMock.On("DeleteResources", mock.Anything, mock.Anything).Return(nil).Times(2)

gatewayConfigBuilderMock := &mocks.GatewayConfigBuilder{}
gatewayConfigBuilderMock.On("Build", mock.Anything, containsPipelines([]telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}), mock.Anything).Return(&gateway.Config{}, nil, nil)

gatewayApplierDeleterMock := &mocks.GatewayApplierDeleter{}
gatewayApplierDeleterMock.On("ApplyResources", mock.Anything, mock.Anything, mock.Anything).Return(nil)

gatewayProberStub := commonStatusStubs.NewDeploymentSetProber(nil)
agentProberStub := commonStatusStubs.NewDaemonSetProber(nil)

sut := New(
fakeClient,
telemetryNamespace,
moduleVersion,
&mocks.AgentConfigBuilder{},
agentApplierDeleterMock,
agentProberStub,
gatewayApplierDeleterMock,
gatewayConfigBuilderMock,
gatewayProberStub,
istioStatusCheckerStub,
&Validator{},
&conditions.ErrorToMessageConverter{})
err1 := sut.Reconcile(context.Background(), &pipeline1)
err2 := sut.Reconcile(context.Background(), &pipeline2)

require.NoError(t, err1)
require.NoError(t, err2)

var updatedPipeline1 telemetryv1alpha1.LogPipeline

var updatedPipeline2 telemetryv1alpha1.LogPipeline

_ = fakeClient.Get(context.Background(), types.NamespacedName{Name: pipeline1.Name}, &updatedPipeline1)
_ = fakeClient.Get(context.Background(), types.NamespacedName{Name: pipeline1.Name}, &updatedPipeline2)

requireHasStatusCondition(t, updatedPipeline1,
conditions.TypeAgentHealthy,
metav1.ConditionTrue,
conditions.ReasonLogAgentNotRequired,
"")
requireHasStatusCondition(t, updatedPipeline2,
conditions.TypeAgentHealthy,
metav1.ConditionTrue,
conditions.ReasonLogAgentNotRequired,
"")

agentApplierDeleterMock.AssertExpectations(t)
gatewayConfigBuilderMock.AssertExpectations(t)
})
}

func TestGetPipelinesRequiringAgents(t *testing.T) {
r := Reconciler{}

t.Run("no pipelines", func(t *testing.T) {
pipelines := []telemetryv1alpha1.LogPipeline{}
require.Empty(t, r.getPipelinesRequiringAgents(pipelines))
})

t.Run("no pipeline requires an agent", func(t *testing.T) {
pipeline1 := testutils.NewLogPipelineBuilder().WithOTLPOutput().WithApplicationInput(false).Build()
pipeline2 := testutils.NewLogPipelineBuilder().WithOTLPOutput().WithApplicationInput(false).Build()
pipelines := []telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}
require.Empty(t, r.getPipelinesRequiringAgents(pipelines))
})

t.Run("some pipelines require an agent", func(t *testing.T) {
pipeline1 := testutils.NewLogPipelineBuilder().WithOTLPOutput().WithApplicationInput(true).Build()
pipeline2 := testutils.NewLogPipelineBuilder().WithOTLPOutput().WithApplicationInput(false).Build()
pipelines := []telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}
require.ElementsMatch(t, []telemetryv1alpha1.LogPipeline{pipeline1}, r.getPipelinesRequiringAgents(pipelines))
})

t.Run("all pipelines require an agent", func(t *testing.T) {
pipeline1 := testutils.NewLogPipelineBuilder().WithOTLPOutput().WithApplicationInput(true).Build()
pipeline2 := testutils.NewLogPipelineBuilder().WithOTLPOutput().WithApplicationInput(true).Build()
pipelines := []telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}
require.ElementsMatch(t, []telemetryv1alpha1.LogPipeline{pipeline1, pipeline2}, r.getPipelinesRequiringAgents(pipelines))
})
}

func requireHasStatusCondition(t *testing.T, pipeline telemetryv1alpha1.LogPipeline, condType string, status metav1.ConditionStatus, reason, message string) {
Expand All @@ -322,3 +510,24 @@ func containsPipeline(p telemetryv1alpha1.LogPipeline) any {
return len(pipelines) == 1 && pipelines[0].Name == p.Name
})
}

func containsPipelines(pp []telemetryv1alpha1.LogPipeline) any {
return mock.MatchedBy(func(pipelines []telemetryv1alpha1.LogPipeline) bool {
if len(pipelines) != len(pp) {
return false
}

pipelineMap := make(map[string]bool)
for _, p := range pipelines {
pipelineMap[p.Name] = true
}

for _, p := range pp {
if !pipelineMap[p.Name] {
return false
}
}

return true
})
}
Loading

0 comments on commit bec97a2

Please sign in to comment.