@@ -12,10 +12,13 @@ import (
1212 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1313 "sigs.k8s.io/yaml"
1414
15+ batchv1alpha1 "github.com/flanksource/batch-runner/pkg/apis/batch/v1"
1516 "github.com/flanksource/commons/logger"
1617 "github.com/flanksource/duty/context"
18+ "github.com/flanksource/duty/shell"
1719 "github.com/flanksource/duty/shutdown"
1820 "github.com/flanksource/gomplate/v3"
21+ "github.com/samber/lo"
1922 "github.com/samber/oops"
2023
2124 "gocloud.dev/pubsub"
@@ -41,23 +44,15 @@ func pretty(o any) string {
4144 return string (b )
4245
4346}
44- func RunConsumer (rootCtx context.Context , config Config ) error {
47+ func RunConsumer (rootCtx context.Context , config * batchv1alpha1. Config ) error {
4548 if config .LogLevel != "" {
4649 logger .StandardLogger ().SetLogLevel (config .LogLevel )
4750 rootCtx .Infof ("Set log level to %s => %v" , config .LogLevel , rootCtx .Logger .GetLevel ())
4851 }
4952
50- if config .client == nil {
51- if client , _ , err := NewClient (); err != nil {
52- return oops .Wrapf (err , "Failed to create Kubernetes client" )
53- } else {
54- config .client = client
55- }
56- }
57-
5853 rootCtx .Infof ("Config: \n %+v" , pretty (config ))
5954
60- sub , err := config . Subscribe (rootCtx )
55+ sub , err := Subscribe (rootCtx , config )
6156 if err != nil {
6257 return oops .Wrapf (err , "Error building URL" )
6358 }
@@ -83,10 +78,15 @@ func RunConsumer(rootCtx context.Context, config Config) error {
8378 time .Sleep (3 * time .Second )
8479 }
8580
86- ctx := rootCtx .WithName (msg .LoggableID )
81+ ctx := rootCtx .WithName (lo . CoalesceOrEmpty ( msg .LoggableID , "unknown" ) )
8782 ctx .Logger .SetLogLevel (config .LogLevel )
8883
89- // Attempt to decode Bas64
84+ client , err := ctx .LocalKubernetes ()
85+ if err != nil {
86+ return oops .Wrapf (err , "Error getting Kubernetes client" )
87+ }
88+
89+ // Attempt to decode Base64
9090 decoded , err := base64 .StdEncoding .DecodeString (string (msg .Body ))
9191 if err != nil {
9292 decoded = msg .Body
@@ -121,7 +121,7 @@ func RunConsumer(rootCtx context.Context, config Config) error {
121121
122122 ctx .Tracef ("pod=%s" , pretty (pod ))
123123
124- p , err := config . client .CoreV1 ().Pods (pod .Namespace ).Create (ctx , & pod , metav1.CreateOptions {})
124+ p , err := client .CoreV1 ().Pods (pod .Namespace ).Create (ctx , & pod , metav1.CreateOptions {})
125125 if p == nil || p .CreationTimestamp .IsZero () {
126126 p = & pod
127127 }
@@ -137,17 +137,44 @@ func RunConsumer(rootCtx context.Context, config Config) error {
137137
138138 ctx .Tracef ("job=%s" , pretty (job ))
139139
140- created , err := config . client .BatchV1 ().Jobs (job .Namespace ).Create (ctx , & job , metav1.CreateOptions {})
140+ created , err := client .BatchV1 ().Jobs (job .Namespace ).Create (ctx , & job , metav1.CreateOptions {})
141141 if created .CreationTimestamp .IsZero () {
142142 created = & job
143143 }
144144
145145 shouldRetry (ctx , msg , created , err )
146+ } else if config .Exec != nil {
147+ exec := * config .Exec
148+ if err := templater .Walk (& exec ); err != nil {
149+ ctx .Errorf ("Error templating exec: %v" , err )
150+ msg .Ack ()
151+ continue
152+ }
153+
154+ ctx .Tracef ("job=%s" , pretty (exec ))
155+
156+ details , err := shell .Run (ctx , exec .ToShellExec ())
157+ if err == nil && details .ExitCode == 0 {
158+ ctx .Tracef (details .String ())
159+ msg .Ack ()
160+ continue
161+ }
162+
163+ _delay := time .Second * 5
164+ if msg .Nackable () {
165+ msg .Nack ()
166+ }
167+ if err != nil {
168+ ctx .Errorf ("Error running, (retrying in %s %v\n %s" , _delay , err , exec .Script )
169+ } else {
170+ ctx .Errorf ("Script returned non-zero exit code: %s" , details )
171+ time .Sleep (_delay )
172+ }
173+
146174 } else {
147175 return fmt .Errorf ("Invalid config, must specify either a job or a pod" )
148176 }
149177 }
150-
151178}
152179
153180func shouldRetry (ctx context.Context , msg * pubsub.Message , accessor metav1.ObjectMetaAccessor , err error ) {
0 commit comments