Skip to content
This repository was archived by the owner on Feb 9, 2025. It is now read-only.

Commit 42b12c8

Browse files
authored
Merge pull request #1 from sebastocorp/feat/add-condition-value-additional-sources
Feat/add condition value additional sources
2 parents d0d3f6f + 9a4a895 commit 42b12c8

8 files changed

+314
-17
lines changed

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ spec:
7373
name: testing-secret
7474
key: RABBITMQ_PASSWORD
7575

76+
# Additional sources to get information from.
77+
# This sources can be used on condition.value
78+
additionalSources:
79+
- apiVersion: apps/v1
80+
kind: Deployment
81+
name: testing-workload
82+
namespace: default
83+
7684
# This is the condition that will trigger the execution of the action.
7785
# The 'key' field admits dot notation, and it's covered by gjson
7886
# Ref: https://github.com/tidwall/gjson
@@ -359,6 +367,73 @@ spec:
359367
value: ""
360368
```
361369
370+
Until now, we have talked about the capabilities of the field `condition.key`, but `condition.value` is really
371+
powerful too. If `additionalSources` is filled, the content of these sources is available to craft complex values.
372+
All you need to do, is to use the pattern `[<list-index>]{{ <GJSON-expression> }}` inside the `condition.value` field
373+
to use some value coming from a source.
374+
375+
> Hey! Sources is a list composed by `workloadRef` + `additionalSources`. This means position [0] is reserved for
376+
> the target workload and higher positions starting from [1] will be filled with additionalSources
377+
378+
Let's see an example:
379+
380+
```yaml
381+
apiVersion: rabbit-stalker.docplanner.com/v1alpha1
382+
kind: WorkloadAction
383+
metadata:
384+
name: workloadaction-sample
385+
spec:
386+
# ...
387+
condition:
388+
389+
# string literal example
390+
key: rabbit@fancy-monk-sample-01
391+
392+
# This will take the value of an annotation named 'node' coming from workloadRef object
393+
value: "[0]{{ metadata.annotations.node }}"
394+
```
395+
396+
You can craft a value adding some string literals at any side of the pattern used to search. The structure will be
397+
replaced by the value found in the source:
398+
399+
```yaml
400+
apiVersion: rabbit-stalker.docplanner.com/v1alpha1
401+
kind: WorkloadAction
402+
metadata:
403+
name: workloadaction-sample
404+
spec:
405+
# ...
406+
condition:
407+
408+
# string literal example
409+
key: rabbit@fancy-monk-sample-01
410+
411+
# This will take the value of an annotation named 'node' coming from the resource in first position at sources list.
412+
# Imagine the value for this annotation is '1'
413+
# The '[0]{{ metadata.annotations.node }}' string will be replaced before the comparison, so the final value will
414+
# be 'rabbit@fancy-monk-sample-01'
415+
value: "rabbit@fancy-monk-sample-0[0]{{ metadata.annotations.node }}"
416+
```
417+
418+
As final feature you can use the patterns as many times as needed to build the final string:
419+
420+
```yaml
421+
apiVersion: rabbit-stalker.docplanner.com/v1alpha1
422+
kind: WorkloadAction
423+
metadata:
424+
name: workloadaction-sample
425+
spec:
426+
# ...
427+
condition:
428+
429+
# string literal example
430+
key: rabbit@fancy-monk-sample-03
431+
432+
# This will take the value from multiples sources in the source list
433+
# The final value will be 'rabbit@fancy-monk-sample-03' for example
434+
value: "rabbit@[1]{{ cluster.name }}-0[0]{{ metadata.annotations.node }}"
435+
```
436+
362437
### Running on the cluster
363438

364439
#### Easy way (recommended)

api/v1alpha1/workloadaction_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ type WorkloadActionSpec struct {
7272
// RabbitConnection represents the connection settings to connect with RabbitMQ admin API
7373
RabbitConnection RabbitConnectionSpec `json:"rabbitConnection"`
7474

75+
// AdditionalSources represent references to Kubernetes resources that whill be available on condition.value
76+
AdditionalSources []corev1.ObjectReference `json:"additionalSources,omitempty"`
77+
7578
// Condition represent a key/value pair found in the JSON of the HTTP response
7679
Condition ConditionSpec `json:"condition"`
7780

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 9 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/rabbit-stalker.docplanner.com_workloadactions.yaml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,71 @@ spec:
5555
- restart
5656
- delete
5757
type: string
58+
additionalSources:
59+
description: AdditionalSources represent references to Kubernetes
60+
resources that whill be available on condition.value
61+
items:
62+
description: "ObjectReference contains enough information to let
63+
you inspect or modify the referred object. --- New uses of this
64+
type are discouraged because of difficulty describing its usage
65+
when embedded in APIs. 1. Ignored fields. It includes many fields
66+
which are not generally honored. For instance, ResourceVersion
67+
and FieldPath are both very rarely valid in actual usage. 2. Invalid
68+
usage help. It is impossible to add specific help for individual
69+
usage. In most embedded usages, there are particular restrictions
70+
like, \"must refer only to types A and B\" or \"UID not honored\"
71+
or \"name must be restricted\". Those cannot be well described
72+
when embedded. 3. Inconsistent validation. Because the usages
73+
are different, the validation rules are different by usage, which
74+
makes it hard for users to predict what will happen. 4. The fields
75+
are both imprecise and overly precise. Kind is not a precise
76+
mapping to a URL. This can produce ambiguity during interpretation
77+
and require a REST mapping. In most cases, the dependency is
78+
on the group,resource tuple and the version of the actual struct
79+
is irrelevant. 5. We cannot easily change it. Because this type
80+
is embedded in many locations, updates to this type will affect
81+
numerous schemas. Don't make new APIs embed an underspecified
82+
API type they do not control. \n Instead of using this type, create
83+
a locally provided and used type that is well-focused on your
84+
reference. For example, ServiceReferences for admission registration:
85+
https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
86+
."
87+
properties:
88+
apiVersion:
89+
description: API version of the referent.
90+
type: string
91+
fieldPath:
92+
description: 'If referring to a piece of an object instead of
93+
an entire object, this string should contain a valid JSON/Go
94+
field access statement, such as desiredState.manifest.containers[2].
95+
For example, if the object reference is to a container within
96+
a pod, this would take on a value like: "spec.containers{name}"
97+
(where "name" refers to the name of the container that triggered
98+
the event) or if no container name is specified "spec.containers[2]"
99+
(container with index 2 in this pod). This syntax is chosen
100+
only to have some well-defined way of referencing a part of
101+
an object. TODO: this design is not final and this field is
102+
subject to change in the future.'
103+
type: string
104+
kind:
105+
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
106+
type: string
107+
name:
108+
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
109+
type: string
110+
namespace:
111+
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
112+
type: string
113+
resourceVersion:
114+
description: 'Specific resourceVersion to which this reference
115+
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
116+
type: string
117+
uid:
118+
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
119+
type: string
120+
type: object
121+
x-kubernetes-map-type: atomic
122+
type: array
58123
condition:
59124
description: Condition represent a key/value pair found in the JSON
60125
of the HTTP response

config/samples/rabbit-stalker_v1alpha1_workloadaction.yaml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ spec:
1818
vhost: "shared"
1919
queue: "your-queue-here"
2020

21-
# Credentials are optional.
21+
# (Optional) Credentials to authenticate against endpoint.
2222
# If set, both are required
2323
credentials:
2424
username:
@@ -30,12 +30,25 @@ spec:
3030
name: testing-secret
3131
key: RABBITMQ_PASSWORD
3232

33+
# (Optional) Additional sources to get information from.
34+
# This sources can be used on condition.value
35+
additionalSources:
36+
- apiVersion: apps/v1
37+
kind: Deployment
38+
name: testing-workload
39+
namespace: default
40+
3341
# Condition under the action is executed.
34-
# The 'key' field admits dot notation, and it's covered by gjson
35-
# Ref: https://github.com/tidwall/gjson
3642
condition:
37-
key: "test"
38-
value: "something"
43+
# The 'key' field admits dot notation, and it's covered by gjson
44+
# Ref: https://github.com/tidwall/gjson
45+
key: |-
46+
consumer_details.#(channel_details.node==rabbit@fancy-monk-sample-01).channel_details.node
47+
48+
# Additional sources can be used here to craft complex values using the following pattern:
49+
# [index]{{ gjson }}
50+
value: |-
51+
[0]{{ metadata.annotations.node }}
3952
4053
# Action to do with the workload when the condition is met
4154
action: "restart"

controllers/workloadaction_controller.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,9 @@ func (r *WorkloadActionReconciler) Reconcile(ctx context.Context, req ctrl.Reque
114114
defer func() {
115115
err = r.Status().Update(ctx, workloadActionManifest)
116116
if err != nil {
117-
LogInfof(ctx, workloadActionConditionUpdateError, req.Name)
117+
LogInfof(ctx, workloadActionConditionUpdateError, err)
118118
}
119+
err = nil
119120
}()
120121

121122
// 6. Schedule periodical request
@@ -125,6 +126,7 @@ func (r *WorkloadActionReconciler) Reconcile(ctx context.Context, req ctrl.Reque
125126
return result, err
126127
}
127128
result = ctrl.Result{
129+
Requeue: true,
128130
RequeueAfter: RequeueTime,
129131
}
130132

controllers/workloadaction_status.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ const (
3636
ConditionReasonInvalidAction = "InvalidAction"
3737
ConditionReasonInvalidActionMessage = "Action is invalid"
3838

39+
// Condition value parsing failed
40+
ConditionReasonConditionValueParsingFailed = "ConditionValueParsingFailed"
41+
ConditionReasonConditionValueParsingFailedMessage = "Condition value parsing process failed"
42+
3943
// Action execution failed
4044
ConditionReasonActionExecutionFailed = "ActionExecutionFailed"
4145
ConditionReasonActionExecutionFailedMessage = "Action failed during execution"

0 commit comments

Comments
 (0)