• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zalando-incubator / stackset-controller / 8738031909

19 Mar 2024 06:41PM UTC coverage: 51.212% (-0.9%) from 52.101%
8738031909

Pull #593

github

linki
some labels
Pull Request #593: [2/3] Add Inline Solution for ConfigMaps

5 of 143 new or added lines in 5 files covered. (3.5%)

766 existing lines in 14 files now uncovered.

3084 of 6022 relevant lines covered (51.21%)

0.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.55
/pkg/core/stack_resources.go
1
package core
2

3
import (
4
        "context"
5
        "fmt"
6
        "sort"
7
        "strconv"
8
        "strings"
9

10
        log "github.com/sirupsen/logrus"
11
        rgv1 "github.com/szuecs/routegroup-client/apis/zalando.org/v1"
12
        zv1 "github.com/zalando-incubator/stackset-controller/pkg/apis/zalando.org/v1"
13
        "github.com/zalando-incubator/stackset-controller/pkg/clientset"
14
        appsv1 "k8s.io/api/apps/v1"
15
        autoscaling "k8s.io/api/autoscaling/v2"
16
        v1 "k8s.io/api/core/v1"
17
        networking "k8s.io/api/networking/v1"
18
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19
        "k8s.io/apimachinery/pkg/labels"
20
        "k8s.io/apimachinery/pkg/util/intstr"
21
        "k8s.io/apimachinery/pkg/util/sets"
22
)
23

24
const (
25
        apiVersionAppsV1 = "apps/v1"
26
        kindDeployment   = "Deployment"
27

28
        SegmentSuffix       = "-traffic-segment"
29
        IngressPredicateKey = "zalando.org/skipper-predicate"
30
)
31

32
type ingressOrRouteGroupSpec interface {
33
        GetAnnotations() map[string]string
34
        GetHosts() []string
35
}
36

37
var (
38
        // set implementation with 0 Byte value
39
        selectorLabels = map[string]struct{}{
40
                StacksetHeritageLabelKey: {},
41
                StackVersionLabelKey:     {},
42
        }
43

44
        // PathTypeImplementationSpecific is the used implementation path type
45
        // for k8s.io/api/networking/v1.HTTPIngressPath resources.
46
        PathTypeImplementationSpecific = networking.PathTypeImplementationSpecific
47
)
48

49
func mapCopy(m map[string]string) map[string]string {
1✔
50
        newMap := map[string]string{}
1✔
51
        for k, v := range m {
2✔
52
                newMap[k] = v
1✔
53
        }
1✔
54
        return newMap
1✔
55
}
56

57
// limitLabels returns a limited set of labels based on the validKeys.
58
func limitLabels(labels map[string]string, validKeys map[string]struct{}) map[string]string {
1✔
59
        newLabels := make(map[string]string, len(labels))
1✔
60
        for k, v := range labels {
2✔
61
                if _, ok := validKeys[k]; ok {
2✔
62
                        newLabels[k] = v
1✔
63
                }
1✔
64
        }
65
        return newLabels
1✔
66
}
67

68
// templateObjectMetaInjectLabels injects labels into a pod template spec.
69
func objectMetaInjectLabels(objectMeta metav1.ObjectMeta, labels map[string]string) metav1.ObjectMeta {
1✔
70
        if objectMeta.Labels == nil {
2✔
71
                objectMeta.Labels = map[string]string{}
1✔
72
        }
1✔
73
        for key, value := range labels {
2✔
74
                if _, ok := objectMeta.Labels[key]; !ok {
2✔
75
                        objectMeta.Labels[key] = value
1✔
76
                }
1✔
77
        }
78
        return objectMeta
1✔
79
}
80

81
func (sc *StackContainer) objectMeta(segment bool) metav1.ObjectMeta {
1✔
82
        resourceLabels := mapCopy(sc.Stack.Labels)
1✔
83

1✔
84
        name := sc.Name()
1✔
85
        if segment {
2✔
86
                name += SegmentSuffix
1✔
87
        }
1✔
88

89
        return metav1.ObjectMeta{
1✔
90
                Name:      name,
1✔
91
                Namespace: sc.Namespace(),
1✔
92
                Annotations: map[string]string{
1✔
93
                        stackGenerationAnnotationKey: strconv.FormatInt(sc.Stack.Generation, 10),
1✔
94
                },
1✔
95
                Labels: resourceLabels,
1✔
96
                OwnerReferences: []metav1.OwnerReference{
1✔
97
                        {
1✔
98
                                APIVersion: APIVersion,
1✔
99
                                Kind:       KindStack,
1✔
100
                                Name:       sc.Name(),
1✔
101
                                UID:        sc.Stack.UID,
1✔
102
                        },
1✔
103
                },
1✔
104
        }
1✔
105
}
106

107
func (sc *StackContainer) resourceMeta() metav1.ObjectMeta {
1✔
108
        return sc.objectMeta(false)
1✔
109
}
1✔
110

111
// getServicePorts gets the service ports to be used for the stack service.
112
func getServicePorts(stackSpec zv1.StackSpecInternal, backendPort *intstr.IntOrString) ([]v1.ServicePort, error) {
1✔
113
        var servicePorts []v1.ServicePort
1✔
114
        if stackSpec.StackSpec.Service == nil ||
1✔
115
                len(stackSpec.StackSpec.Service.Ports) == 0 {
2✔
116

1✔
117
                servicePorts = servicePortsFromContainers(
1✔
118
                        stackSpec.StackSpec.PodTemplate.Spec.Containers,
1✔
119
                )
1✔
120
        } else {
2✔
121
                servicePorts = stackSpec.StackSpec.Service.Ports
1✔
122
        }
1✔
123

124
        // validate that one port in the list maps to the backendPort.
125
        if backendPort != nil {
2✔
126
                for _, port := range servicePorts {
2✔
127
                        switch backendPort.Type {
1✔
128
                        case intstr.Int:
1✔
129
                                if port.Port == backendPort.IntVal {
2✔
130
                                        return servicePorts, nil
1✔
131
                                }
1✔
132
                        case intstr.String:
1✔
133
                                if port.Name == backendPort.StrVal {
2✔
134
                                        return servicePorts, nil
1✔
135
                                }
1✔
136
                        }
137
                }
138

139
                return nil, fmt.Errorf("no service ports matching backendPort '%s'", backendPort.String())
1✔
140
        }
141

142
        return servicePorts, nil
1✔
143
}
144

145
// servicePortsFromTemplate gets service port from pod template.
146
func servicePortsFromContainers(containers []v1.Container) []v1.ServicePort {
1✔
147
        ports := make([]v1.ServicePort, 0)
1✔
148
        for i, container := range containers {
2✔
149
                for j, port := range container.Ports {
2✔
150
                        name := fmt.Sprintf("port-%d-%d", i, j)
1✔
151
                        if port.Name != "" {
2✔
152
                                name = port.Name
1✔
153
                        }
1✔
154
                        servicePort := v1.ServicePort{
1✔
155
                                Name:       name,
1✔
156
                                Protocol:   port.Protocol,
1✔
157
                                Port:       port.ContainerPort,
1✔
158
                                TargetPort: intstr.FromInt(int(port.ContainerPort)),
1✔
159
                        }
1✔
160
                        // set default protocol if not specified
1✔
161
                        if servicePort.Protocol == "" {
2✔
162
                                servicePort.Protocol = v1.ProtocolTCP
1✔
163
                        }
1✔
164
                        ports = append(ports, servicePort)
1✔
165
                }
166
        }
167
        return ports
1✔
168
}
169

170
func (sc *StackContainer) selector() map[string]string {
1✔
171
        return limitLabels(sc.Stack.Labels, selectorLabels)
1✔
172
}
1✔
173

174
func (sc *StackContainer) GenerateDeployment() *appsv1.Deployment {
1✔
175
        stack := sc.Stack
1✔
176

1✔
177
        desiredReplicas := sc.stackReplicas
1✔
178
        if sc.prescalingActive {
2✔
179
                desiredReplicas = sc.prescalingReplicas
1✔
180
        }
1✔
181

182
        var updatedReplicas *int32
1✔
183

1✔
184
        if desiredReplicas != 0 && !sc.ScaledDown() {
2✔
185
                // Stack scaled up, rescale the deployment if it's at 0 replicas, or if HPA is unused and we don't run autoscaling
1✔
186
                if sc.deploymentReplicas == 0 || (!sc.IsAutoscaled() && desiredReplicas != sc.deploymentReplicas) {
2✔
187
                        updatedReplicas = wrapReplicas(desiredReplicas)
1✔
188
                }
1✔
189
        } else {
1✔
190
                // Stack scaled down (manually or because it doesn't receive traffic), check if we need to scale down the deployment
1✔
191
                if sc.deploymentReplicas != 0 {
2✔
192
                        updatedReplicas = wrapReplicas(0)
1✔
193
                }
1✔
194
        }
195

196
        if updatedReplicas == nil {
2✔
197
                updatedReplicas = wrapReplicas(sc.deploymentReplicas)
1✔
198
        }
1✔
199

200
        var strategy *appsv1.DeploymentStrategy
1✔
201
        if stack.Spec.StackSpec.Strategy != nil {
2✔
202
                strategy = stack.Spec.StackSpec.Strategy.DeepCopy()
1✔
203
        }
1✔
204

205
        embeddedCopy := stack.Spec.StackSpec.PodTemplate.EmbeddedObjectMeta.DeepCopy()
1✔
206

1✔
207
        templateObjectMeta := metav1.ObjectMeta{
1✔
208
                Annotations: embeddedCopy.Annotations,
1✔
209
                Labels:      embeddedCopy.Labels,
1✔
210
        }
1✔
211

1✔
212
        deployment := &appsv1.Deployment{
1✔
213
                ObjectMeta: sc.resourceMeta(),
1✔
214
                Spec: appsv1.DeploymentSpec{
1✔
215
                        Replicas:        updatedReplicas,
1✔
216
                        MinReadySeconds: sc.Stack.Spec.StackSpec.MinReadySeconds,
1✔
217
                        Selector: &metav1.LabelSelector{
1✔
218
                                MatchLabels: sc.selector(),
1✔
219
                        },
1✔
220
                        Template: v1.PodTemplateSpec{
1✔
221
                                ObjectMeta: objectMetaInjectLabels(templateObjectMeta, stack.Labels),
1✔
222
                                Spec:       *stack.Spec.StackSpec.PodTemplate.Spec.DeepCopy(),
1✔
223
                        },
1✔
224
                },
1✔
225
        }
1✔
226
        if strategy != nil {
2✔
227
                deployment.Spec.Strategy = *strategy
1✔
228
        }
1✔
229
        return deployment
1✔
230
}
231

232
func (sc *StackContainer) GenerateHPAToSegment() (
233
        *autoscaling.HorizontalPodAutoscaler,
234
        error,
235
) {
1✔
236
        return sc.generateHPA(true)
1✔
237
}
1✔
238

239
func (sc *StackContainer) GenerateHPA() (
240
        *autoscaling.HorizontalPodAutoscaler,
241
        error,
242
) {
1✔
243
        return sc.generateHPA(false)
1✔
244

1✔
245
}
1✔
246

247
func (sc *StackContainer) generateHPA(toSegment bool) (
248
        *autoscaling.HorizontalPodAutoscaler,
249
        error,
250
) {
1✔
251
        autoscalerSpec := sc.Stack.Spec.StackSpec.Autoscaler
1✔
252
        trafficWeight := sc.actualTrafficWeight
1✔
253

1✔
254
        if autoscalerSpec == nil {
1✔
UNCOV
255
                return nil, nil
×
UNCOV
256
        }
×
257

258
        if sc.ScaledDown() {
2✔
259
                return nil, nil
1✔
260
        }
1✔
261

262
        result := &autoscaling.HorizontalPodAutoscaler{
1✔
263
                ObjectMeta: sc.resourceMeta(),
1✔
264
                TypeMeta: metav1.TypeMeta{
1✔
265
                        Kind:       "HorizontalPodAutoscaler",
1✔
266
                        APIVersion: "autoscaling/v2",
1✔
267
                },
1✔
268
                Spec: autoscaling.HorizontalPodAutoscalerSpec{
1✔
269
                        ScaleTargetRef: autoscaling.CrossVersionObjectReference{
1✔
270
                                APIVersion: apiVersionAppsV1,
1✔
271
                                Kind:       kindDeployment,
1✔
272
                                Name:       sc.Name(),
1✔
273
                        },
1✔
274
                },
1✔
275
        }
1✔
276

1✔
277
        result.Spec.MinReplicas = autoscalerSpec.MinReplicas
1✔
278
        result.Spec.MaxReplicas = autoscalerSpec.MaxReplicas
1✔
279

1✔
280
        ingressResourceName := sc.stacksetName
1✔
281
        if toSegment {
2✔
282
                ingressResourceName = sc.Name() + SegmentSuffix
1✔
283
        }
1✔
284

285
        metrics, annotations, err := convertCustomMetrics(
1✔
286
                ingressResourceName,
1✔
287
                sc.Name(),
1✔
288
                sc.Namespace(),
1✔
289
                autoscalerMetricsList(autoscalerSpec.Metrics),
1✔
290
                trafficWeight,
1✔
291
        )
1✔
292

1✔
293
        if err != nil {
1✔
294
                return nil, err
×
295
        }
×
296
        result.Spec.Metrics = metrics
1✔
297
        result.Annotations = mergeLabels(result.Annotations, annotations)
1✔
298
        result.Spec.Behavior = autoscalerSpec.Behavior
1✔
299

1✔
300
        // If prescaling is enabled, ensure we have at least `precalingReplicas` pods
1✔
301
        if sc.prescalingActive && (result.Spec.MinReplicas == nil || *result.Spec.MinReplicas < sc.prescalingReplicas) {
1✔
UNCOV
302
                pr := sc.prescalingReplicas
×
UNCOV
303
                result.Spec.MinReplicas = &pr
×
UNCOV
304
        }
×
305

306
        return result, nil
1✔
307
}
308

309
func (sc *StackContainer) GenerateService() (*v1.Service, error) {
1✔
310
        // get service ports to be used for the service
1✔
311
        var backendPort *intstr.IntOrString
1✔
312
        // Ingress or external managed Ingress
1✔
313
        if sc.HasBackendPort() {
1✔
UNCOV
314
                backendPort = sc.backendPort
×
UNCOV
315
        }
×
316

317
        servicePorts, err := getServicePorts(sc.Stack.Spec, backendPort)
1✔
318
        if err != nil {
1✔
UNCOV
319
                return nil, err
×
UNCOV
320
        }
×
321

322
        metaObj := sc.resourceMeta()
1✔
323
        stackSpec := sc.Stack.Spec
1✔
324
        if stackSpec.StackSpec.Service != nil {
2✔
325
                metaObj.Annotations = mergeLabels(
1✔
326
                        metaObj.Annotations,
1✔
327
                        stackSpec.StackSpec.Service.Annotations,
1✔
328
                )
1✔
329
        }
1✔
330
        return &v1.Service{
1✔
331
                ObjectMeta: metaObj,
1✔
332
                Spec: v1.ServiceSpec{
1✔
333
                        Selector: sc.selector(),
1✔
334
                        Type:     v1.ServiceTypeClusterIP,
1✔
335
                        Ports:    servicePorts,
1✔
336
                },
1✔
337
        }, nil
1✔
338
}
339

340
func (sc *StackContainer) stackHostnames(
341
        spec ingressOrRouteGroupSpec,
342
        segment bool,
343
) ([]string, error) {
1✔
344
        // The Ingress segment uses the original hostnames
1✔
345
        if segment {
2✔
346
                return spec.GetHosts(), nil
1✔
347
        }
1✔
348
        result := sets.NewString()
1✔
349

1✔
350
        // Old-style autogenerated hostnames
1✔
351
        for _, host := range spec.GetHosts() {
2✔
352
                for _, domain := range sc.clusterDomains {
2✔
353
                        if strings.HasSuffix(host, domain) {
2✔
354
                                result.Insert(fmt.Sprintf("%s.%s", sc.Name(), domain))
1✔
355
                        } else {
2✔
356
                                log.Debugf(
1✔
357
                                        "Ingress host: %s suffix did not match cluster-domain %s",
1✔
358
                                        host,
1✔
359
                                        domain,
1✔
360
                                )
1✔
361
                        }
1✔
362
                }
363
        }
364
        return result.List(), nil
1✔
365
}
366

367
func (sc *StackContainer) GenerateIngress() (*networking.Ingress, error) {
1✔
368
        return sc.generateIngress(false)
1✔
369
}
1✔
370

371
func (sc *StackContainer) GenerateIngressSegment() (
372
        *networking.Ingress,
373
        error,
374
) {
1✔
375
        res, err := sc.generateIngress(true)
1✔
376
        if err != nil || res == nil {
2✔
377
                return res, err
1✔
378
        }
1✔
379

380
        // Synchronize annotations specified in the StackSet.
381
        res.Annotations = syncAnnotations(
1✔
382
                res.Annotations,
1✔
383
                sc.syncAnnotationsInIngress,
1✔
384
                sc.ingressAnnotationsToSync,
1✔
385
        )
1✔
386

1✔
387
        if predVal, ok := res.Annotations[IngressPredicateKey]; !ok || predVal == "" {
2✔
388
                res.Annotations = mergeLabels(
1✔
389
                        res.Annotations,
1✔
390
                        map[string]string{IngressPredicateKey: sc.trafficSegment()},
1✔
391
                )
1✔
392
        } else {
2✔
393
                res.Annotations = mergeLabels(
1✔
394
                        res.Annotations,
1✔
395
                        map[string]string{
1✔
396
                                IngressPredicateKey: sc.trafficSegment() + " && " + predVal,
1✔
397
                        },
1✔
398
                )
1✔
399
        }
1✔
400

401
        return res, nil
1✔
402
}
403

404
func (sc *StackContainer) generateIngress(segment bool) (
405
        *networking.Ingress,
406
        error,
407
) {
1✔
408

1✔
409
        if !sc.HasBackendPort() || sc.ingressSpec == nil {
2✔
410
                return nil, nil
1✔
411
        }
1✔
412

413
        hostnames, err := sc.stackHostnames(sc.ingressSpec, segment)
1✔
414
        if err != nil {
1✔
UNCOV
415
                return nil, err
×
UNCOV
416
        }
×
417
        if len(hostnames) == 0 {
2✔
418
                return nil, nil
1✔
419
        }
1✔
420

421
        rules := make([]networking.IngressRule, 0, len(hostnames))
1✔
422
        for _, hostname := range hostnames {
2✔
423
                rules = append(rules, networking.IngressRule{
1✔
424
                        IngressRuleValue: networking.IngressRuleValue{
1✔
425
                                HTTP: &networking.HTTPIngressRuleValue{
1✔
426
                                        Paths: []networking.HTTPIngressPath{
1✔
427
                                                {
1✔
428
                                                        PathType: &PathTypeImplementationSpecific,
1✔
429
                                                        Path:     sc.ingressSpec.Path,
1✔
430
                                                        Backend: networking.IngressBackend{
1✔
431
                                                                Service: &networking.IngressServiceBackend{
1✔
432
                                                                        Name: sc.Name(),
1✔
433
                                                                        Port: networking.ServiceBackendPort{
1✔
434
                                                                                Name:   sc.backendPort.StrVal,
1✔
435
                                                                                Number: sc.backendPort.IntVal,
1✔
436
                                                                        },
1✔
437
                                                                },
1✔
438
                                                        },
1✔
439
                                                },
1✔
440
                                        },
1✔
441
                                },
1✔
442
                        },
1✔
443
                        Host: hostname,
1✔
444
                })
1✔
445
        }
1✔
446

447
        // sort rules by hostname for a stable order
448
        sort.Slice(rules, func(i, j int) bool {
2✔
449
                return rules[i].Host < rules[j].Host
1✔
450
        })
1✔
451

452
        result := &networking.Ingress{
1✔
453
                ObjectMeta: sc.objectMeta(segment),
1✔
454
                Spec: networking.IngressSpec{
1✔
455
                        Rules: rules,
1✔
456
                },
1✔
457
        }
1✔
458

1✔
459
        // insert annotations
1✔
460
        result.Annotations = mergeLabels(
1✔
461
                result.Annotations,
1✔
462
                sc.ingressSpec.GetAnnotations(),
1✔
463
        )
1✔
464

1✔
465
        return result, nil
1✔
466
}
467

468
func (sc *StackContainer) GenerateRouteGroup() (*rgv1.RouteGroup, error) {
1✔
469
        return sc.generateRouteGroup(false)
1✔
470
}
1✔
471

472
func (sc *StackContainer) GenerateRouteGroupSegment() (
473
        *rgv1.RouteGroup,
474
        error,
475
) {
1✔
476
        res, err := sc.generateRouteGroup(true)
1✔
477
        if err != nil || res == nil {
2✔
478
                return res, err
1✔
479
        }
1✔
480

481
        // Synchronize annotations specified in the StackSet.
482
        res.Annotations = syncAnnotations(
1✔
483
                res.Annotations,
1✔
484
                sc.syncAnnotationsInRouteGroup,
1✔
485
                sc.ingressAnnotationsToSync,
1✔
486
        )
1✔
487

1✔
488
        segmentedRoutes := []rgv1.RouteGroupRouteSpec{}
1✔
489
        for _, r := range res.Spec.Routes {
2✔
490
                r.Predicates = append(r.Predicates, sc.trafficSegment())
1✔
491
                segmentedRoutes = append(segmentedRoutes, r)
1✔
492
        }
1✔
493
        res.Spec.Routes = segmentedRoutes
1✔
494

1✔
495
        return res, nil
1✔
496
}
497

498
func (sc *StackContainer) generateRouteGroup(segment bool) (
499
        *rgv1.RouteGroup,
500
        error,
501
) {
1✔
502
        if !sc.HasBackendPort() || sc.routeGroupSpec == nil {
2✔
503
                return nil, nil
1✔
504
        }
1✔
505

506
        hostnames, err := sc.stackHostnames(sc.routeGroupSpec, segment)
1✔
507
        if err != nil {
1✔
UNCOV
508
                return nil, err
×
UNCOV
509
        }
×
510
        if len(hostnames) == 0 {
2✔
511
                return nil, nil
1✔
512
        }
1✔
513

514
        result := &rgv1.RouteGroup{
1✔
515
                ObjectMeta: sc.objectMeta(segment),
1✔
516
                Spec: rgv1.RouteGroupSpec{
1✔
517
                        Hosts: hostnames,
1✔
518
                        Backends: []rgv1.RouteGroupBackend{
1✔
519
                                {
1✔
520
                                        Name:        sc.Name(),
1✔
521
                                        Type:        rgv1.ServiceRouteGroupBackend,
1✔
522
                                        ServiceName: sc.Name(),
1✔
523
                                        ServicePort: sc.backendPort.IntValue(),
1✔
524
                                        Algorithm:   sc.routeGroupSpec.LBAlgorithm,
1✔
525
                                },
1✔
526
                        },
1✔
527
                        DefaultBackends: []rgv1.RouteGroupBackendReference{
1✔
528
                                {
1✔
529
                                        BackendName: sc.Name(),
1✔
530
                                        Weight:      100,
1✔
531
                                },
1✔
532
                        },
1✔
533
                },
1✔
534
        }
1✔
535

1✔
536
        result.Spec.Routes = sc.routeGroupSpec.Routes
1✔
537

1✔
538
        // validate not overlapping with main backend
1✔
539
        for _, backend := range sc.routeGroupSpec.AdditionalBackends {
1✔
UNCOV
540
                if backend.Name == sc.Name() {
×
UNCOV
541
                        return nil, fmt.Errorf("invalid additionalBackend '%s', overlaps with Stack name", backend.Name)
×
UNCOV
542
                }
×
UNCOV
543
                if backend.ServiceName == sc.Name() {
×
UNCOV
544
                        return nil, fmt.Errorf("invalid additionalBackend '%s', serviceName '%s' overlaps with Stack name", backend.Name, backend.ServiceName)
×
UNCOV
545
                }
×
UNCOV
546
                result.Spec.Backends = append(result.Spec.Backends, backend)
×
547
        }
548

549
        // sort backends to ensure have a consistent generated RouteGroup resource
550
        sort.Slice(result.Spec.Backends, func(i, j int) bool {
1✔
UNCOV
551
                return result.Spec.Backends[i].Name < result.Spec.Backends[j].Name
×
UNCOV
552
        })
×
553

554
        // insert annotations
555
        result.Annotations = mergeLabels(
1✔
556
                result.Annotations,
1✔
557
                sc.routeGroupSpec.GetAnnotations(),
1✔
558
        )
1✔
559

1✔
560
        return result, nil
1✔
561
}
562

563
func (sc *StackContainer) trafficSegment() string {
1✔
564
        return fmt.Sprintf(
1✔
565
                segmentString,
1✔
566
                sc.segmentLowerLimit,
1✔
567
                sc.segmentUpperLimit,
1✔
568
        )
1✔
569
}
1✔
570

571
func (sc *StackContainer) UpdateObjectMeta(objMeta *metav1.ObjectMeta) *metav1.ObjectMeta {
1✔
572
        metaObj := sc.resourceMeta()
1✔
573
        objMeta.OwnerReferences = metaObj.OwnerReferences
1✔
574
        objMeta.Labels = mergeLabels(metaObj.Labels, objMeta.Labels)
1✔
575
        objMeta.Annotations = mergeLabels(metaObj.Annotations, objMeta.Annotations)
1✔
576

1✔
577
        return objMeta
1✔
578
}
1✔
579

NEW
580
func (sc *StackContainer) GenerateConfigMaps(ctx context.Context, client clientset.Interface) ([]*v1.ConfigMap, error) {
×
NEW
581
        result := []*v1.ConfigMap{}
×
NEW
582

×
NEW
583
        for _, configResource := range sc.Stack.Spec.ConfigurationResources {
×
NEW
584
                if configResource.IsConfigMap() {
×
NEW
585
                        metaObj := sc.resourceMeta()
×
NEW
586
                        metaObj.Name = metaObj.Name + "-" + configResource.GetName()
×
NEW
587
                        metaObj.OwnerReferences = []metav1.OwnerReference{ // maybe that should be metaObj.OwnerReferences instead
×
NEW
588
                                {
×
NEW
589
                                        APIVersion: APIVersion,
×
NEW
590
                                        Kind:       KindStack,
×
NEW
591
                                        Name:       sc.Name(),
×
NEW
592
                                        UID:        sc.Stack.UID,
×
NEW
593
                                },
×
NEW
594
                        }
×
NEW
595

×
NEW
596
                        base := &v1.ConfigMap{
×
NEW
597
                                ObjectMeta: metaObj,
×
NEW
598
                                Data:       configResource.ConfigMap.Data,
×
NEW
599
                        }
×
NEW
600

×
NEW
601
                        result = append(result, base)
×
NEW
602
                }
×
603

NEW
604
                if configResource.IsConfigMapRef() {
×
NEW
605
                        configMap, err := client.CoreV1().ConfigMaps(sc.Namespace()).Get(ctx, configResource.GetName(), metav1.GetOptions{})
×
NEW
606
                        if err != nil {
×
NEW
607
                                return nil, err
×
NEW
608
                        }
×
609

NEW
610
                        metaObj := sc.resourceMeta()
×
NEW
611

×
NEW
612
                        configMap.ObjectMeta.OwnerReferences = metaObj.OwnerReferences
×
NEW
613
                        configMap.ObjectMeta.Labels = mergeLabels(metaObj.Labels, configMap.ObjectMeta.Labels)
×
NEW
614
                        configMap.ObjectMeta.Annotations = mergeLabels(metaObj.Annotations, configMap.ObjectMeta.Annotations)
×
NEW
615

×
NEW
616
                        result = append(result, configMap)
×
617
                }
618
        }
619

NEW
620
        return result, nil
×
621
}
622

623
func (sc *StackContainer) GenerateStackStatus() *zv1.StackStatus {
1✔
624
        prescaling := zv1.PrescalingStatus{}
1✔
625
        if sc.prescalingActive {
2✔
626
                prescaling = zv1.PrescalingStatus{
1✔
627
                        Active:               sc.prescalingActive,
1✔
628
                        Replicas:             sc.prescalingReplicas,
1✔
629
                        DesiredTrafficWeight: sc.prescalingDesiredTrafficWeight,
1✔
630
                        LastTrafficIncrease:  wrapTime(sc.prescalingLastTrafficIncrease),
1✔
631
                }
1✔
632
        }
1✔
633
        return &zv1.StackStatus{
1✔
634
                ActualTrafficWeight:  sc.actualTrafficWeight,
1✔
635
                DesiredTrafficWeight: sc.desiredTrafficWeight,
1✔
636
                Replicas:             sc.createdReplicas,
1✔
637
                ReadyReplicas:        sc.readyReplicas,
1✔
638
                UpdatedReplicas:      sc.updatedReplicas,
1✔
639
                DesiredReplicas:      sc.deploymentReplicas,
1✔
640
                Prescaling:           prescaling,
1✔
641
                NoTrafficSince:       wrapTime(sc.noTrafficSince),
1✔
642
                LabelSelector:        labels.Set(sc.selector()).String(),
1✔
643
        }
1✔
644
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc