-
Notifications
You must be signed in to change notification settings - Fork 352
/
Copy pathbuild_kit.go
169 lines (141 loc) · 6.6 KB
/
build_kit.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 integration
import (
"context"
"github.com/pkg/errors"
v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/trait"
"github.com/apache/camel-k/pkg/util/digest"
"github.com/apache/camel-k/pkg/util/kubernetes"
)
func newBuildKitAction() Action {
return &buildKitAction{}
}
type buildKitAction struct {
baseAction
}
func (action *buildKitAction) Name() string {
return "build-kit"
}
func (action *buildKitAction) CanHandle(integration *v1.Integration) bool {
return integration.Status.Phase == v1.IntegrationPhaseBuildingKit
}
func (action *buildKitAction) Handle(ctx context.Context, integration *v1.Integration) (*v1.Integration, error) {
// TODO: we may need to add a timeout strategy, i.e give up after some time in case of an unrecoverable error.
// Check if the Integration has changed and requires a rebuild
hash, err := digest.ComputeForIntegration(integration)
if err != nil {
return nil, err
}
if hash != integration.Status.Digest {
action.L.Info("Integration needs a rebuild")
integration.Initialize()
integration.Status.Digest = hash
return integration, nil
}
//
// IntegrationKit may be nil if its being upgraded
//
if integration.Status.IntegrationKit != nil {
// IntegrationKit fully defined so find it
action.L.Debugf("Finding integration kit %s for integration %s\n", integration.Status.IntegrationKit.Name, integration.Name)
kit, err := kubernetes.GetIntegrationKit(ctx, action.client, integration.Status.IntegrationKit.Name, integration.Status.IntegrationKit.Namespace)
if err != nil {
return nil, errors.Wrapf(err, "unable to find integration kit %s/%s, %s", integration.Status.IntegrationKit.Namespace, integration.Status.IntegrationKit.Name, err)
}
if kit.Labels[v1.IntegrationKitTypeLabel] == v1.IntegrationKitTypePlatform {
match, err := integrationMatches(integration, kit)
if err != nil {
return nil, errors.Wrapf(err, "unable to match any integration kit with integration %s/%s", integration.Namespace, integration.Name)
} else if !match {
// We need to re-generate a kit, or search for a new one that
// matches the integration, so let's remove the association
// with the kit.
//
// All tests & conditionals check for a nil assignment
//
action.L.Debug("No match found between integration and integrationkit. Resetting integration's integrationkit to empty", "integration", integration.Name, "integrationkit", integration.Status.IntegrationKit.Name, "namespace", integration.Namespace)
integration.SetIntegrationKit(nil)
return integration, nil
}
}
if kit.Status.Phase == v1.IntegrationKitPhaseError {
integration.Status.Phase = v1.IntegrationPhaseError
integration.SetIntegrationKit(kit)
return integration, nil
}
if kit.Status.Phase == v1.IntegrationKitPhaseReady {
integration.Status.Phase = v1.IntegrationPhaseDeploying
integration.SetIntegrationKit(kit)
return integration, nil
}
return nil, nil
}
action.L.Debug("No kit specified in integration status so looking up", "integration", integration.Name, "namespace", integration.Namespace)
existingKits, err := lookupKitsForIntegration(ctx, action.client, integration)
if err != nil {
return nil, errors.Wrapf(err, "failed to lookup kits for integration %s/%s", integration.Namespace, integration.Name)
}
action.L.Debug("Applying traits to integration", "integration", integration.Name, "namespace", integration.Namespace)
env, err := trait.Apply(ctx, action.client, integration, nil)
if err != nil {
return nil, errors.Wrapf(err, "failed to apply traits to integration %s/%s", integration.Namespace, integration.Name)
}
action.L.Debug("Searching integration kits to assign to integration", "integration", integration.Name, "namespace", integration.Namespace)
var integrationKit *v1.IntegrationKit
kits:
for _, kit := range env.IntegrationKits {
kit := kit
for i := range existingKits {
k := &existingKits[i]
action.L.Debug("Comparing existing kit with environment", "env kit", kit.Name, "existing kit", k.Name)
match, err := kitMatches(&kit, k)
if err != nil {
return nil, errors.Wrapf(err, "error occurred matches integration kits with environment for integration %s/%s", integration.Namespace, integration.Name)
}
if match {
if integrationKit == nil ||
integrationKit.Status.Phase != v1.IntegrationKitPhaseReady && k.Status.Phase == v1.IntegrationKitPhaseReady ||
integrationKit.Status.Phase == v1.IntegrationKitPhaseReady && k.Status.Phase == v1.IntegrationKitPhaseReady && k.HasHigherPriorityThan(integrationKit) {
integrationKit = k
action.L.Debug("Found matching kit", "integration kit", integrationKit.Name)
}
continue kits
} else {
action.L.Debug("Cannot match kits", "env kit", kit.Name, "existing kit", k.Name)
}
}
action.L.Debug("No existing kit available for integration. Creating a new one.", "integration", integration.Name, "namespace", integration.Namespace, "integration kit", kit.Name)
if err := action.client.Create(ctx, &kit); err != nil {
return nil, errors.Wrapf(err, "failed to create new integration kit for integration %s/%s", integration.Namespace, integration.Name)
}
if integrationKit == nil {
integrationKit = &kit
}
}
if integrationKit != nil {
action.L.Debug("Setting integration kit for integration", "integration", integration.Name, "namespace", integration.Namespace, "integration kit", integrationKit.Name)
// Set the kit name so the next handle loop, will fall through the
// same path as integration with a user defined kit
integration.SetIntegrationKit(integrationKit)
if integrationKit.Status.Phase == v1.IntegrationKitPhaseReady {
integration.Status.Phase = v1.IntegrationPhaseDeploying
}
} else {
action.L.Debug("Not yet able to assign an integration kit to integration", "integration", integration.Name, "namespace", integration.Namespace)
}
return integration, nil
}