Skip to content

Commit 3ce4cad

Browse files
authored
[Feature] Allow to direct use image (#538)
1 parent 397712d commit 3ce4cad

File tree

6 files changed

+292
-9
lines changed

6 files changed

+292
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Change Log
22

33
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
4+
- Added Image Discovery type in ArangoDeployment spec
45
- Prevent Agency Members recreation
56
- Added Customizable Volumes and VolumeMounts for ArangoDB server container
67
- Added MemoryOverride flag for ArangoDB >= 3.6.3

pkg/apis/deployment/v1/deployment_spec.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@ func validatePullPolicy(v v1.PullPolicy) error {
4747

4848
// DeploymentSpec contains the spec part of a ArangoDeployment resource.
4949
type DeploymentSpec struct {
50-
Mode *DeploymentMode `json:"mode,omitempty"`
51-
Environment *Environment `json:"environment,omitempty"`
52-
StorageEngine *StorageEngine `json:"storageEngine,omitempty"`
53-
Image *string `json:"image,omitempty"`
54-
ImagePullPolicy *v1.PullPolicy `json:"imagePullPolicy,omitempty"`
55-
ImagePullSecrets []string `json:"imagePullSecrets,omitempty"`
56-
DowntimeAllowed *bool `json:"downtimeAllowed,omitempty"`
57-
DisableIPv6 *bool `json:"disableIPv6,omitempty"`
50+
Mode *DeploymentMode `json:"mode,omitempty"`
51+
Environment *Environment `json:"environment,omitempty"`
52+
StorageEngine *StorageEngine `json:"storageEngine,omitempty"`
53+
Image *string `json:"image,omitempty"`
54+
ImagePullPolicy *v1.PullPolicy `json:"imagePullPolicy,omitempty"`
55+
ImagePullSecrets []string `json:"imagePullSecrets,omitempty"`
56+
ImageDiscoveryMode *DeploymentImageDiscoveryModeSpec `json:"imageDiscoveryMode,omitempty"`
57+
DowntimeAllowed *bool `json:"downtimeAllowed,omitempty"`
58+
DisableIPv6 *bool `json:"disableIPv6,omitempty"`
5859

5960
NetworkAttachedVolumes *bool `json:"networkAttachedVolumes,omitempty"`
6061

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Adam Janikowski
21+
//
22+
23+
package v1
24+
25+
import "fmt"
26+
27+
type DeploymentImageDiscoveryModeSpec string
28+
29+
func NewDeploymentImageDiscoveryModeSpec(mode DeploymentImageDiscoveryModeSpec) *DeploymentImageDiscoveryModeSpec {
30+
return &mode
31+
}
32+
33+
const (
34+
DeploymentImageDiscoveryDirectMode = "direct"
35+
DeploymentImageDiscoveryKubeletMode = "kubelet"
36+
)
37+
38+
func (d DeploymentImageDiscoveryModeSpec) Validate() error {
39+
switch d {
40+
case DeploymentImageDiscoveryKubeletMode:
41+
return nil
42+
case DeploymentImageDiscoveryDirectMode:
43+
return nil
44+
default:
45+
return fmt.Errorf("mode %s is not supported", d)
46+
}
47+
}
48+
49+
func (d *DeploymentImageDiscoveryModeSpec) Get() DeploymentImageDiscoveryModeSpec {
50+
if d == nil {
51+
return DeploymentImageDiscoveryKubeletMode
52+
}
53+
54+
return *d
55+
}

pkg/apis/deployment/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Tomasz Mielech <[email protected]>
21+
//
22+
23+
package deployment
24+
25+
import (
26+
"testing"
27+
28+
"github.com/arangodb/go-driver"
29+
30+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
31+
32+
"github.com/arangodb/kube-arangodb/pkg/util"
33+
34+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
35+
core "k8s.io/api/core/v1"
36+
)
37+
38+
func createTestDiscoveredImages(image, version, id string) api.ImageInfoList {
39+
return api.ImageInfoList{
40+
{
41+
Image: image,
42+
ArangoDBVersion: driver.Version(version),
43+
ImageID: id,
44+
Enterprise: false,
45+
},
46+
}
47+
}
48+
49+
func TestEnsurePod_ArangoDB_ImagePropagation(t *testing.T) {
50+
image := "arangodb/test:0.0.0"
51+
version := "0.0.0"
52+
imageID := "arangodb/test@sha256:xxx"
53+
54+
discoveredImages := createTestDiscoveredImages(image, version, imageID)
55+
56+
testCases := []testCaseStruct{
57+
{
58+
Name: "Agent Pod with defined image",
59+
ArangoDeployment: &api.ArangoDeployment{
60+
Spec: api.DeploymentSpec{
61+
Image: util.NewString(image),
62+
Authentication: noAuthentication,
63+
TLS: noTLS,
64+
ImagePullPolicy: util.NewPullPolicy(core.PullAlways),
65+
},
66+
},
67+
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
68+
deployment.status.last = api.DeploymentStatus{
69+
Members: api.DeploymentStatusMembers{
70+
Agents: api.MemberStatusList{
71+
firstAgentStatus,
72+
},
73+
},
74+
Images: discoveredImages,
75+
}
76+
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
77+
},
78+
ExpectedEvent: "member agent is created",
79+
ExpectedPod: core.Pod{
80+
Spec: core.PodSpec{
81+
Volumes: []core.Volume{
82+
k8sutil.CreateVolumeEmptyDir(k8sutil.ArangodVolumeName),
83+
},
84+
Containers: []core.Container{
85+
{
86+
Name: k8sutil.ServerContainerName,
87+
Image: imageID,
88+
Command: createTestCommandForAgent(firstAgentStatus.ID, false, false, false),
89+
Ports: createTestPorts(),
90+
VolumeMounts: []core.VolumeMount{
91+
k8sutil.ArangodVolumeMount(),
92+
},
93+
Resources: emptyResources,
94+
LivenessProbe: createTestLivenessProbe(false, "", k8sutil.ArangoPort),
95+
ImagePullPolicy: core.PullAlways,
96+
SecurityContext: securityContext.NewSecurityContext(),
97+
},
98+
},
99+
RestartPolicy: core.RestartPolicyNever,
100+
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
101+
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
102+
Subdomain: testDeploymentName + "-int",
103+
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
104+
false, ""),
105+
},
106+
},
107+
},
108+
{
109+
Name: "Agent Pod with defined image and defined kubelet mode",
110+
ArangoDeployment: &api.ArangoDeployment{
111+
Spec: api.DeploymentSpec{
112+
Image: util.NewString(image),
113+
ImageDiscoveryMode: api.NewDeploymentImageDiscoveryModeSpec(api.DeploymentImageDiscoveryKubeletMode),
114+
Authentication: noAuthentication,
115+
TLS: noTLS,
116+
ImagePullPolicy: util.NewPullPolicy(core.PullAlways),
117+
},
118+
},
119+
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
120+
deployment.status.last = api.DeploymentStatus{
121+
Members: api.DeploymentStatusMembers{
122+
Agents: api.MemberStatusList{
123+
firstAgentStatus,
124+
},
125+
},
126+
Images: discoveredImages,
127+
}
128+
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
129+
},
130+
ExpectedEvent: "member agent is created",
131+
ExpectedPod: core.Pod{
132+
Spec: core.PodSpec{
133+
Volumes: []core.Volume{
134+
k8sutil.CreateVolumeEmptyDir(k8sutil.ArangodVolumeName),
135+
},
136+
Containers: []core.Container{
137+
{
138+
Name: k8sutil.ServerContainerName,
139+
Image: imageID,
140+
Command: createTestCommandForAgent(firstAgentStatus.ID, false, false, false),
141+
Ports: createTestPorts(),
142+
VolumeMounts: []core.VolumeMount{
143+
k8sutil.ArangodVolumeMount(),
144+
},
145+
Resources: emptyResources,
146+
LivenessProbe: createTestLivenessProbe(false, "", k8sutil.ArangoPort),
147+
ImagePullPolicy: core.PullAlways,
148+
SecurityContext: securityContext.NewSecurityContext(),
149+
},
150+
},
151+
RestartPolicy: core.RestartPolicyNever,
152+
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
153+
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
154+
Subdomain: testDeploymentName + "-int",
155+
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
156+
false, ""),
157+
},
158+
},
159+
},
160+
{
161+
Name: "Agent Pod with defined image and defined direct mode",
162+
ArangoDeployment: &api.ArangoDeployment{
163+
Spec: api.DeploymentSpec{
164+
Image: util.NewString(image),
165+
ImageDiscoveryMode: api.NewDeploymentImageDiscoveryModeSpec(api.DeploymentImageDiscoveryDirectMode),
166+
Authentication: noAuthentication,
167+
TLS: noTLS,
168+
ImagePullPolicy: util.NewPullPolicy(core.PullAlways),
169+
},
170+
},
171+
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
172+
deployment.status.last = api.DeploymentStatus{
173+
Members: api.DeploymentStatusMembers{
174+
Agents: api.MemberStatusList{
175+
firstAgentStatus,
176+
},
177+
},
178+
Images: discoveredImages,
179+
}
180+
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
181+
},
182+
ExpectedEvent: "member agent is created",
183+
ExpectedPod: core.Pod{
184+
Spec: core.PodSpec{
185+
Volumes: []core.Volume{
186+
k8sutil.CreateVolumeEmptyDir(k8sutil.ArangodVolumeName),
187+
},
188+
Containers: []core.Container{
189+
{
190+
Name: k8sutil.ServerContainerName,
191+
Image: image,
192+
Command: createTestCommandForAgent(firstAgentStatus.ID, false, false, false),
193+
Ports: createTestPorts(),
194+
VolumeMounts: []core.VolumeMount{
195+
k8sutil.ArangodVolumeMount(),
196+
},
197+
Resources: emptyResources,
198+
LivenessProbe: createTestLivenessProbe(false, "", k8sutil.ArangoPort),
199+
ImagePullPolicy: core.PullAlways,
200+
SecurityContext: securityContext.NewSecurityContext(),
201+
},
202+
},
203+
RestartPolicy: core.RestartPolicyNever,
204+
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
205+
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
206+
Subdomain: testDeploymentName + "-int",
207+
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
208+
false, ""),
209+
},
210+
},
211+
},
212+
}
213+
214+
runTestCases(t, testCases...)
215+
}

pkg/deployment/resources/pod_creator_arangod.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,13 @@ func (a *ArangoDContainer) GetProbes() (*core.Probe, *core.Probe, error) {
9494
}
9595

9696
func (a *ArangoDContainer) GetImage() string {
97-
return a.imageInfo.ImageID
97+
switch a.spec.ImageDiscoveryMode.Get() {
98+
case api.DeploymentImageDiscoveryDirectMode:
99+
// In case of direct mode ignore discovery
100+
return util.StringOrDefault(a.spec.Image, a.imageInfo.ImageID)
101+
default:
102+
return a.imageInfo.ImageID
103+
}
98104
}
99105

100106
func (a *ArangoDContainer) GetEnvs() []core.EnvVar {

0 commit comments

Comments
 (0)