/
sync_apiservice_v311_00.go
134 lines (112 loc) · 6.4 KB
/
sync_apiservice_v311_00.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
package operator
import (
"fmt"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
appsclientv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1"
operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1"
scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1"
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
"github.com/openshift/library-go/pkg/operator/resource/resourcecread"
"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
"github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets"
)
// syncAPIServiceController_v311_00_to_latest takes care of synchronizing (not upgrading) the thing we're managing.
// most of the time the sync method will be good for a large span of minor versions
func syncAPIServiceController_v311_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) {
versionAvailability := operatorsv1alpha1.VersionAvailablity{
Version: operatorConfig.Spec.Version,
}
errors := []error{}
var err error
requiredNamespace := resourceread.ReadNamespaceV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/ns.yaml"))
_, _, err = resourceapply.ApplyNamespace(c.corev1Client, requiredNamespace)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "ns", err))
}
requiredClusterRole := resourceread.ReadClusterRoleV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/clusterrole.yaml"))
_, _, err = resourceapply.ApplyClusterRole(c.rbacv1Client, requiredClusterRole)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "svc", err))
}
requiredClusterRoleBinding := resourceread.ReadClusterRoleBindingV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/clusterrolebinding.yaml"))
_, _, err = resourceapply.ApplyClusterRoleBinding(c.rbacv1Client, requiredClusterRoleBinding)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "svc", err))
}
requiredService := resourceread.ReadServiceV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/svc.yaml"))
_, _, err = resourceapply.ApplyService(c.corev1Client, requiredService)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "svc", err))
}
requiredSA := resourceread.ReadServiceAccountV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/sa.yaml"))
_, saModified, err := resourceapply.ApplyServiceAccount(c.corev1Client, requiredSA)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "sa", err))
}
// TODO create a new configmap whenever the data value changes
_, configMapModified, err := manageAPIServiceConfigMap_v311_00_to_latest(c.corev1Client, operatorConfig)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "configmap", err))
}
_, signingCABundleModified, err := manageSigningCABundle(c.corev1Client)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "signing-key", err))
}
forceDeployment := operatorConfig.ObjectMeta.Generation != operatorConfig.Status.ObservedGeneration
if saModified { // SA modification can cause new tokens
forceDeployment = true
}
if signingCABundleModified {
forceDeployment = true
}
if configMapModified {
forceDeployment = true
}
// we have attempted to update our configmaps and secrets, now it is time to create the DS
// TODO check basic preconditions here
actualDeployment, _, err := manageAPIServiceDeployment_v311_00_to_latest(c.appsv1Client, operatorConfig, previousAvailability, forceDeployment)
if err != nil {
errors = append(errors, fmt.Errorf("%q: %v", "deployment", err))
}
return resourcemerge.ApplyGenerationAvailability(versionAvailability, actualDeployment, errors...), errors
}
func manageAPIServiceConfigMap_v311_00_to_latest(client coreclientv1.ConfigMapsGetter, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig) (*corev1.ConfigMap, bool, error) {
configMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/cm.yaml"))
defaultConfig := v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml")
requiredConfigMap, _, err := resourcemerge.MergeConfigMap(configMap, "controller-config.yaml", nil, defaultConfig, operatorConfig.Spec.APIServiceCABundleInjectorConfig.Raw)
if err != nil {
return nil, false, err
}
return resourceapply.ApplyConfigMap(client, requiredConfigMap)
}
func manageAPIServiceDeployment_v311_00_to_latest(client appsclientv1.DeploymentsGetter, options *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity, forceDeployment bool) (*appsv1.Deployment, bool, error) {
required := resourceread.ReadDeploymentV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/deployment.yaml"))
required.Spec.Template.Spec.Containers[0].Image = options.Spec.ImagePullSpec
required.Spec.Template.Spec.Containers[0].Args = append(required.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("-v=%d", options.Spec.Logging.Level))
return resourceapply.ApplyDeployment(client, required, resourcemerge.ExpectedDeploymentGeneration(required, previousAvailability), forceDeployment)
}
// TODO manage rotation in addition to initial creation
func manageSigningCABundle(client coreclientv1.CoreV1Interface) (*corev1.ConfigMap, bool, error) {
configMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/signing-cabundle.yaml"))
existing, err := client.ConfigMaps(configMap.Namespace).Get(configMap.Name, metav1.GetOptions{})
if !apierrors.IsNotFound(err) {
return existing, false, err
}
secret := resourceread.ReadSecretV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/signing-secret.yaml"))
currentSigningKeySecret, err := client.Secrets(secret.Namespace).Get(secret.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return existing, false, err
}
if err != nil {
return existing, false, err
}
if len(currentSigningKeySecret.Data["tls.crt"]) == 0 {
return existing, false, err
}
configMap.Data["cabundle.crt"] = string(currentSigningKeySecret.Data["tls.crt"])
return resourceapply.ApplyConfigMap(client, configMap)
}