-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathactuator.go
142 lines (116 loc) · 5.29 KB
/
actuator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Gardener contributors
//
// SPDX-License-Identifier: Apache-2.0
package lifecycle
import (
"context"
"errors"
"fmt"
"time"
extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller"
"github.com/gardener/gardener/extensions/pkg/controller/extension"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
"github.com/gardener/gardener/pkg/component"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/gardener/gardener-extension-shoot-rsyslog-relp/imagevector"
apisconfig "github.com/gardener/gardener-extension-shoot-rsyslog-relp/pkg/apis/config"
api "github.com/gardener/gardener-extension-shoot-rsyslog-relp/pkg/apis/rsyslog"
"github.com/gardener/gardener-extension-shoot-rsyslog-relp/pkg/component/rsyslogrelpconfigcleaner"
"github.com/gardener/gardener-extension-shoot-rsyslog-relp/pkg/constants"
)
const (
// ActuatorName is the name of the rsyslog relp actuator.
ActuatorName = constants.ServiceName + "-actuator"
releaseName = "rsyslog-relp-configurator"
configurationCleanerReleaseName = "rsyslog-relp-configuration-cleaner"
deletionTimeout = time.Minute * 2
nodeExporterTextfileCollectorDir = "/var/lib/node-exporter/textfile-collector"
)
// NewActuator returns an actuator responsible for Extension resources.
func NewActuator(client client.Client, decoder runtime.Decoder, config apisconfig.Configuration, chartRendererFactory extensionscontroller.ChartRendererFactory) extension.Actuator {
return &actuator{
client: client,
decoder: decoder,
config: config,
chartRendererFactory: chartRendererFactory,
}
}
type actuator struct {
chartRendererFactory extensionscontroller.ChartRendererFactory
client client.Client
decoder runtime.Decoder
config apisconfig.Configuration
}
// Reconcile reconciles the extension resource.
func (a *actuator) Reconcile(ctx context.Context, _ logr.Logger, ex *extensionsv1alpha1.Extension) error {
namespace := ex.GetNamespace()
rsyslogRelpConfig := &api.RsyslogRelpConfig{}
if err := runtime.DecodeInto(a.decoder, ex.Spec.ProviderConfig.Raw, rsyslogRelpConfig); err != nil {
return fmt.Errorf("failed to decode provider config: %w", err)
}
return deployMonitoringConfig(ctx, a.client, namespace, rsyslogRelpConfig.AuditConfig)
}
// Delete deletes the extension resource.
func (a *actuator) Delete(ctx context.Context, _ logr.Logger, ex *extensionsv1alpha1.Extension) error {
namespace := ex.GetNamespace()
cluster, err := extensionscontroller.GetCluster(ctx, a.client, namespace)
if err != nil {
return err
}
if cluster.Shoot == nil {
return errors.New("cluster.shoot is not yet populated")
}
if err := deleteMonitoringConfig(ctx, a.client, namespace); err != nil {
return fmt.Errorf("failed cleaning up monitoring configuration: %w", err)
}
return cleanRsyslogRelpConfiguration(ctx, cluster, a.client, namespace)
}
// ForceDelete deletes the extension resource.
func (a *actuator) ForceDelete(_ context.Context, _ logr.Logger, _ *extensionsv1alpha1.Extension) error {
return nil
}
// Restore restores the extension resource.
func (a *actuator) Restore(ctx context.Context, log logr.Logger, ex *extensionsv1alpha1.Extension) error {
return a.Reconcile(ctx, log, ex)
}
// Migrate migrates the extension resource.
func (a *actuator) Migrate(_ context.Context, _ logr.Logger, _ *extensionsv1alpha1.Extension) error {
return nil
}
func cleanRsyslogRelpConfiguration(ctx context.Context, cluster *extensionscontroller.Cluster, client client.Client, namespace string) error {
// If the Shoot is hibernated, we don't have Nodes. Hence, there is no need to clean up anything.
if extensionscontroller.IsHibernated(cluster) {
return nil
}
alpineImage, err := imagevector.ImageVector().FindImage(imagevector.ImageNameAlpine)
if err != nil {
return fmt.Errorf("failed to find the alpine image: %w", err)
}
pauseImage, err := imagevector.ImageVector().FindImage(imagevector.ImageNamePauseContainer)
if err != nil {
return fmt.Errorf("failed to find the pause image: %w", err)
}
values := rsyslogrelpconfigcleaner.Values{
AlpineImage: alpineImage.String(),
PauseContainerImage: pauseImage.String(),
}
cleaner := rsyslogrelpconfigcleaner.New(client, namespace, values)
// If the Shoot is in deletion, then there is no need to deploy the component to clean up the rsyslog
// configuration from Nodes. The Shoot deletion flow ensures that the Worker is deleted before
// the Extension deletion. Hence, there are no Nodes, no need to deploy the configuration cleaner component.
//
// However, we should still try to destroy the
// configuration cleaner component, in case it failed to be cleaned up in a previous reconciliation
// where the extension was deleted before the shoot deletion was triggered.
if cluster.Shoot.DeletionTimestamp == nil {
if err := component.OpWait(cleaner).Deploy(ctx); err != nil {
return fmt.Errorf("failed to deploy the rsyslog relp configuration cleaner component: %w", err)
}
}
if err := component.OpDestroyAndWait(cleaner).Destroy(ctx); err != nil {
return fmt.Errorf("failed to destroy the rsyslog relp configuration cleaner component: %w", err)
}
return nil
}