Skip to content

Commit 2e7a95f

Browse files
authored
Merge pull request #71 from arangodb/resources
Moved low level resource (pod,pvc,secret,service) creation & inspection to resources sub-package.
2 parents 81809c0 + d76295a commit 2e7a95f

23 files changed

+423
-234
lines changed

pkg/deployment/reconcile_context_impl.go renamed to pkg/deployment/context_impl.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,35 @@ import (
2828
driver "github.com/arangodb/go-driver"
2929
"k8s.io/api/core/v1"
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/client-go/kubernetes"
3132

3233
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
34+
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
3335
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
3436
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3537
)
3638

3739
// GetAPIObject returns the deployment as k8s object.
38-
func (d *Deployment) GetAPIObject() metav1.Object {
40+
func (d *Deployment) GetAPIObject() k8sutil.APIObject {
3941
return d.apiObject
4042
}
4143

44+
// GetServerGroupIterator returns the deployment as ServerGroupIterator.
45+
func (d *Deployment) GetServerGroupIterator() resources.ServerGroupIterator {
46+
return d.apiObject
47+
}
48+
49+
// GetKubeCli returns the kubernetes client
50+
func (d *Deployment) GetKubeCli() kubernetes.Interface {
51+
return d.deps.KubeCli
52+
}
53+
54+
// GetNamespace returns the kubernetes namespace that contains
55+
// this deployment.
56+
func (d *Deployment) GetNamespace() string {
57+
return d.apiObject.GetNamespace()
58+
}
59+
4260
// GetSpec returns the current specification
4361
func (d *Deployment) GetSpec() api.DeploymentSpec {
4462
return d.apiObject.Spec

pkg/deployment/deployment.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636

3737
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
3838
"github.com/arangodb/kube-arangodb/pkg/deployment/reconcile"
39+
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
3940
"github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned"
4041
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
4142
"github.com/arangodb/kube-arangodb/pkg/util/retry"
@@ -94,6 +95,7 @@ type Deployment struct {
9495
recentInspectionErrors int
9596
clusterScalingIntegration *clusterScalingIntegration
9697
reconciler *reconcile.Reconciler
98+
resources *resources.Resources
9799
}
98100

99101
// New creates a new Deployment from the given API object.
@@ -112,6 +114,7 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De
112114
clientCache: newClientCache(deps.KubeCli, apiObject),
113115
}
114116
d.reconciler = reconcile.NewReconciler(deps.Log, d)
117+
d.resources = resources.NewResources(deps.Log, d)
115118
if d.status.AcceptedSpec == nil {
116119
// We've validated the spec, so let's use it from now.
117120
d.status.AcceptedSpec = apiObject.Spec.DeepCopy()
@@ -167,13 +170,13 @@ func (d *Deployment) run() {
167170

168171
if d.status.State == api.DeploymentStateNone {
169172
// Create secrets
170-
if err := d.createSecrets(d.apiObject); err != nil {
173+
if err := d.resources.EnsureSecrets(); err != nil {
171174
d.failOnError(err, "Failed to create secrets")
172175
return
173176
}
174177

175178
// Create services
176-
if err := d.createServices(d.apiObject); err != nil {
179+
if err := d.resources.EnsureServices(); err != nil {
177180
d.failOnError(err, "Failed to create services")
178181
return
179182
}
@@ -185,13 +188,13 @@ func (d *Deployment) run() {
185188
}
186189

187190
// Create PVCs
188-
if err := d.ensurePVCs(d.apiObject); err != nil {
191+
if err := d.resources.EnsurePVCs(); err != nil {
189192
d.failOnError(err, "Failed to create persistent volume claims")
190193
return
191194
}
192195

193196
// Create pods
194-
if err := d.ensurePods(d.apiObject); err != nil {
197+
if err := d.resources.EnsurePods(); err != nil {
195198
d.failOnError(err, "Failed to create pods")
196199
return
197200
}
@@ -266,18 +269,18 @@ func (d *Deployment) handleArangoDeploymentUpdatedEvent(event *deploymentEvent)
266269
log.Debug().Strs("fields", resetFields).Msg("Found modified immutable fields")
267270
}
268271
if err := newAPIObject.Spec.Validate(); err != nil {
269-
d.createEvent(k8sutil.NewErrorEvent("Validation failed", err, d.apiObject))
272+
d.CreateEvent(k8sutil.NewErrorEvent("Validation failed", err, d.apiObject))
270273
// Try to reset object
271274
if err := d.updateCRSpec(d.apiObject.Spec); err != nil {
272275
log.Error().Err(err).Msg("Restore original spec failed")
273-
d.createEvent(k8sutil.NewErrorEvent("Restore original failed", err, d.apiObject))
276+
d.CreateEvent(k8sutil.NewErrorEvent("Restore original failed", err, d.apiObject))
274277
}
275278
return nil
276279
}
277280
if len(resetFields) > 0 {
278281
for _, fieldName := range resetFields {
279282
log.Debug().Str("field", fieldName).Msg("Reset immutable field")
280-
d.createEvent(k8sutil.NewImmutableFieldEvent(fieldName, d.apiObject))
283+
d.CreateEvent(k8sutil.NewImmutableFieldEvent(fieldName, d.apiObject))
281284
}
282285
}
283286

@@ -302,9 +305,9 @@ func (d *Deployment) handleArangoDeploymentUpdatedEvent(event *deploymentEvent)
302305
return nil
303306
}
304307

305-
// createEvent creates a given event.
308+
// CreateEvent creates a given event.
306309
// On error, the error is logged.
307-
func (d *Deployment) createEvent(evt *v1.Event) {
310+
func (d *Deployment) CreateEvent(evt *v1.Event) {
308311
_, err := d.eventsCli.Create(evt)
309312
if err != nil {
310313
d.deps.Log.Error().Err(err).Interface("event", *evt).Msg("Failed to record event")

pkg/deployment/deployment_inspector.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,41 +46,45 @@ func (d *Deployment) inspectDeployment(lastInterval time.Duration) time.Duration
4646
// Ensure we have image info
4747
if retrySoon, err := d.ensureImages(d.apiObject); err != nil {
4848
hasError = true
49-
d.createEvent(k8sutil.NewErrorEvent("Image detection failed", err, d.apiObject))
49+
d.CreateEvent(k8sutil.NewErrorEvent("Image detection failed", err, d.apiObject))
5050
} else if retrySoon {
5151
nextInterval = minInspectionInterval
5252
}
5353

5454
// Inspection of generated resources needed
55-
if err := d.inspectPods(); err != nil {
55+
if err := d.resources.InspectPods(); err != nil {
5656
hasError = true
57-
d.createEvent(k8sutil.NewErrorEvent("Pod inspection failed", err, d.apiObject))
57+
d.CreateEvent(k8sutil.NewErrorEvent("Pod inspection failed", err, d.apiObject))
5858
}
5959

6060
// Create scale/update plan
6161
if err := d.reconciler.CreatePlan(); err != nil {
6262
hasError = true
63-
d.createEvent(k8sutil.NewErrorEvent("Plan creation failed", err, d.apiObject))
63+
d.CreateEvent(k8sutil.NewErrorEvent("Plan creation failed", err, d.apiObject))
6464
}
6565

6666
// Execute current step of scale/update plan
6767
retrySoon, err := d.reconciler.ExecutePlan(ctx)
6868
if err != nil {
6969
hasError = true
70-
d.createEvent(k8sutil.NewErrorEvent("Plan execution failed", err, d.apiObject))
70+
d.CreateEvent(k8sutil.NewErrorEvent("Plan execution failed", err, d.apiObject))
7171
}
7272
if retrySoon {
7373
nextInterval = minInspectionInterval
7474
}
7575

7676
// Ensure all resources are created
77-
if err := d.ensurePVCs(d.apiObject); err != nil {
77+
if err := d.resources.EnsureServices(); err != nil {
7878
hasError = true
79-
d.createEvent(k8sutil.NewErrorEvent("PVC creation failed", err, d.apiObject))
79+
d.CreateEvent(k8sutil.NewErrorEvent("Service creation failed", err, d.apiObject))
8080
}
81-
if err := d.ensurePods(d.apiObject); err != nil {
81+
if err := d.resources.EnsurePVCs(); err != nil {
8282
hasError = true
83-
d.createEvent(k8sutil.NewErrorEvent("Pod creation failed", err, d.apiObject))
83+
d.CreateEvent(k8sutil.NewErrorEvent("PVC creation failed", err, d.apiObject))
84+
}
85+
if err := d.resources.EnsurePods(); err != nil {
86+
hasError = true
87+
d.CreateEvent(k8sutil.NewErrorEvent("Pod creation failed", err, d.apiObject))
8488
}
8589

8690
// Update next interval (on errors)

pkg/deployment/images.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"strings"
3030

3131
"github.com/rs/zerolog"
32-
"k8s.io/api/core/v1"
3332
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3433
"k8s.io/client-go/kubernetes"
3534

@@ -40,7 +39,6 @@ import (
4039

4140
const (
4241
dockerPullableImageIDPrefix = "docker-pullable://"
43-
imageIDAndVersionRole = "id" // Role use by identification pods
4442
)
4543

4644
type imagesBuilder struct {
@@ -99,7 +97,7 @@ func (ib *imagesBuilder) Run(ctx context.Context) (bool, error) {
9997
// When no pod exists, it is created, otherwise the ID is fetched & version detected.
10098
// Returns: retrySoon, error
10199
func (ib *imagesBuilder) fetchArangoDBImageIDAndVersion(ctx context.Context, image string) (bool, error) {
102-
role := imageIDAndVersionRole
100+
role := k8sutil.ImageIDAndVersionRole
103101
id := fmt.Sprintf("%0x", sha1.Sum([]byte(image)))[:6]
104102
podName := k8sutil.CreatePodName(ib.APIObject.GetName(), role, id, "")
105103
ns := ib.APIObject.GetNamespace()
@@ -175,9 +173,3 @@ func (ib *imagesBuilder) fetchArangoDBImageIDAndVersion(ctx context.Context, ima
175173
// Come back soon to inspect the pod
176174
return true, nil
177175
}
178-
179-
// isArangoDBImageIDAndVersionPod returns true if the given pod is used for fetching image ID and ArangoDB version of an image
180-
func isArangoDBImageIDAndVersionPod(p v1.Pod) bool {
181-
role, found := p.GetLabels()[k8sutil.LabelKeyRole]
182-
return found && role == imageIDAndVersionRole
183-
}

pkg/deployment/reconcile/action_context.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ type ActionContext interface {
6565
DeletePvc(pvcName string) error
6666
}
6767

68-
// NewActionContext creates a new ActionContext implementation.
69-
func NewActionContext(log zerolog.Logger, context ReconcileContext) ActionContext {
68+
// newActionContext creates a new ActionContext implementation.
69+
func newActionContext(log zerolog.Logger, context Context) ActionContext {
7070
return &actionContext{
7171
log: log,
7272
context: context,
@@ -76,7 +76,7 @@ func NewActionContext(log zerolog.Logger, context ReconcileContext) ActionContex
7676
// actionContext implements ActionContext
7777
type actionContext struct {
7878
log zerolog.Logger
79-
context ReconcileContext
79+
context Context
8080
}
8181

8282
// Gets the specified mode of deployment

pkg/deployment/reconcile/reconcile_context.go renamed to pkg/deployment/reconcile/context.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ import (
2727

2828
driver "github.com/arangodb/go-driver"
2929
"k8s.io/api/core/v1"
30-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3130

3231
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
3332
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
33+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3434
)
3535

36-
// ReconcileContext provides methods to the reconcile package.
37-
type ReconcileContext interface {
36+
// Context provides methods to the reconcile package.
37+
type Context interface {
3838
// GetAPIObject returns the deployment as k8s object.
39-
GetAPIObject() metav1.Object
39+
GetAPIObject() k8sutil.APIObject
4040
// GetSpec returns the current specification of the deployment
4141
GetSpec() api.DeploymentSpec
4242
// GetStatus returns the current status of the deployment

pkg/deployment/reconcile/plan_executor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func (d *Reconciler) ExecutePlan(ctx context.Context) (bool, error) {
113113
// Returns true if the action is completely finished, false in case
114114
// the start time needs to be recorded and a ready condition needs to be checked.
115115
func (d *Reconciler) createAction(ctx context.Context, log zerolog.Logger, action api.Action) Action {
116-
actionCtx := NewActionContext(log, d.context)
116+
actionCtx := newActionContext(log, d.context)
117117
switch action.Type {
118118
case api.ActionTypeAddMember:
119119
return NewAddMemberAction(log, action, actionCtx)

pkg/deployment/reconcile/reconciler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ import "github.com/rs/zerolog"
2828
// in line with its (changed) specification.
2929
type Reconciler struct {
3030
log zerolog.Logger
31-
context ReconcileContext
31+
context Context
3232
}
3333

3434
// NewReconciler creates a new reconciler with given context.
35-
func NewReconciler(log zerolog.Logger, context ReconcileContext) *Reconciler {
35+
func NewReconciler(log zerolog.Logger, context Context) *Reconciler {
3636
return &Reconciler{
3737
log: log,
3838
context: context,
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 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 Ewout Prangsma
21+
//
22+
23+
package resources
24+
25+
import (
26+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
27+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
28+
"k8s.io/api/core/v1"
29+
"k8s.io/client-go/kubernetes"
30+
)
31+
32+
// ServerGroupIterator provides a helper to callback on every server
33+
// group of the deployment.
34+
type ServerGroupIterator interface {
35+
// ForeachServerGroup calls the given callback for all server groups.
36+
// If the callback returns an error, this error is returned and no other server
37+
// groups are processed.
38+
// Groups are processed in this order: agents, single, dbservers, coordinators, syncmasters, syncworkers
39+
ForeachServerGroup(cb func(group api.ServerGroup, spec api.ServerGroupSpec, status *api.MemberStatusList) error, status *api.DeploymentStatus) error
40+
}
41+
42+
// Context provides all functions needed by the Resources service
43+
// to perform its service.
44+
type Context interface {
45+
// GetAPIObject returns the deployment as k8s object.
46+
GetAPIObject() k8sutil.APIObject
47+
// GetServerGroupIterator returns the deployment as ServerGroupIterator.
48+
GetServerGroupIterator() ServerGroupIterator
49+
// GetSpec returns the current specification of the deployment
50+
GetSpec() api.DeploymentSpec
51+
// GetStatus returns the current status of the deployment
52+
GetStatus() api.DeploymentStatus
53+
// UpdateStatus replaces the status of the deployment with the given status and
54+
// updates the resources in k8s.
55+
UpdateStatus(status api.DeploymentStatus, force ...bool) error
56+
// GetKubeCli returns the kubernetes client
57+
GetKubeCli() kubernetes.Interface
58+
// GetNamespace returns the namespace that contains the deployment
59+
GetNamespace() string
60+
// createEvent creates a given event.
61+
// On error, the error is logged.
62+
CreateEvent(evt *v1.Event)
63+
// GetOwnedPods returns a list of all pods owned by the deployment.
64+
GetOwnedPods() ([]v1.Pod, error)
65+
}

pkg/deployment/resources/errors.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 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 Ewout Prangsma
21+
//
22+
23+
package resources
24+
25+
import "github.com/pkg/errors"
26+
27+
var (
28+
maskAny = errors.WithStack
29+
)

0 commit comments

Comments
 (0)