-
Notifications
You must be signed in to change notification settings - Fork 109
/
Copy pathinstall.go
116 lines (101 loc) · 4.67 KB
/
install.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
/*
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"context"
"fmt"
"strings"
mf "github.com/manifestival/manifestival"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"knative.dev/operator/pkg/apis/operator/base"
"knative.dev/operator/pkg/apis/operator/v1beta1"
"knative.dev/pkg/logging"
)
var (
role mf.Predicate = mf.Any(mf.ByKind("ClusterRole"), mf.ByKind("Role"))
rolebinding mf.Predicate = mf.Any(mf.ByKind("ClusterRoleBinding"), mf.ByKind("RoleBinding"))
webhook mf.Predicate = mf.Any(mf.ByKind("MutatingWebhookConfiguration"), mf.ByKind("ValidatingWebhookConfiguration"))
webhookDependentResources mf.Predicate = byGV(schema.GroupKind{Group: "networking.internal.knative.dev", Kind: "Certificate"})
gatewayNotMatch = "no matches for kind \"Gateway\""
)
// Install applies the manifest resources for the given version and updates the given
// status accordingly.
func Install(ctx context.Context, manifest *mf.Manifest, instance base.KComponent) error {
logger := logging.FromContext(ctx)
logger.Debug("Installing manifest")
status := instance.GetStatus()
// The Operator needs a higher level of permissions if it 'bind's non-existent roles.
// To avoid this, we strictly order the manifest application as (Cluster)Roles, then
// (Cluster)RoleBindings, then the rest of the manifest.
if err := manifest.Filter(role).Apply(); err != nil {
status.MarkInstallFailed(err.Error())
return fmt.Errorf("failed to apply (cluster)roles: %w", err)
}
if err := manifest.Filter(rolebinding).Apply(); err != nil {
status.MarkInstallFailed(err.Error())
return fmt.Errorf("failed to apply (cluster)rolebindings: %w", err)
}
if err := manifest.Filter(mf.Not(mf.Any(role, rolebinding, webhook, webhookDependentResources))).Apply(); err != nil {
status.MarkInstallFailed(err.Error())
if ks, ok := instance.(*v1beta1.KnativeServing); ok && strings.Contains(err.Error(), gatewayNotMatch) &&
(ks.Spec.Ingress == nil || ks.Spec.Ingress.Istio.Enabled) {
errMessage := fmt.Errorf("please install istio or disable the istio ingress plugin: %w", err)
status.MarkInstallFailed(errMessage.Error())
return errMessage
}
return fmt.Errorf("failed to apply non rbac manifest: %w", err)
}
return nil
}
// InstallWebhookConfigs applies the Webhook manifest resources and updates the given status accordingly.
func InstallWebhookConfigs(ctx context.Context, manifest *mf.Manifest, instance base.KComponent) error {
status := instance.GetStatus()
if err := manifest.Filter(webhook).Apply(); err != nil {
status.MarkInstallFailed(err.Error())
return fmt.Errorf("failed to apply webhooks: %w", err)
}
return nil
}
// InstallWebhookDependentResources applies the Webhook dependent resources updates the given status accordingly.
func InstallWebhookDependentResources(ctx context.Context, manifest *mf.Manifest, instance base.KComponent) error {
status := instance.GetStatus()
if err := manifest.Filter(webhookDependentResources).Apply(); err != nil {
status.MarkInstallFailed(err.Error())
return fmt.Errorf("failed to apply webhooks: %w", err)
}
return nil
}
// MarkStatusSuccess updates the component status to success.
func MarkStatusSuccess(ctx context.Context, manifest *mf.Manifest, instance base.KComponent) error {
status := instance.GetStatus()
status.MarkInstallSucceeded()
status.SetVersion(TargetVersion(instance))
return nil
}
// Uninstall removes all resources except CRDs, which are never deleted automatically.
func Uninstall(manifest *mf.Manifest) error {
if err := manifest.Filter(mf.NoCRDs, mf.Not(mf.Any(role, rolebinding))).Delete(mf.IgnoreNotFound(true)); err != nil {
return fmt.Errorf("failed to remove non-crd/non-rbac resources: %w", err)
}
// Delete Roles last, as they may be useful for human operators to clean up.
if err := manifest.Filter(mf.Any(role, rolebinding)).Delete(mf.IgnoreNotFound(true)); err != nil {
return fmt.Errorf("failed to remove rbac: %w", err)
}
return nil
}
func byGV(gk schema.GroupKind) mf.Predicate {
return func(u *unstructured.Unstructured) bool {
return u.GroupVersionKind().GroupKind() == gk
}
}