-
Notifications
You must be signed in to change notification settings - Fork 66
Enable setting of Temporal headers through cli #883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
internal/temporalcli/commands.yaml
Outdated
| May be passed multiple times to set multiple headers. | ||
| Can also be made available via environment variable as | ||
| `TEMPORAL_GRPC_META_[name]`. | ||
| - name: headers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this setting should only be on commands where it makes sense, namely workflow start, execute, query, signal, and update (and any signal-with-start or update-with-start).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Limited it to:
- workflow execute
- workflow execute-update-with-start
- workflow signal
- workflow signal-with-start
- workflow start
- workflow start-update-with-start
- workflow query
- workflow update start
- workflow update execute
| newOpts := cctx.StoredClientOptions | ||
| cliHeaderPropagator, err := cliHeaderPropagator(updateStartOpts.Headers) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| newOpts.ContextPropagators = append(newOpts.ContextPropagators, cliHeaderPropagator) | ||
| execClient, err = client.NewClientFromExisting(cl, newOpts) | ||
| if err != nil { | ||
| return fmt.Errorf("unable to create header-propagator client: %w", err) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think instead of this approach where we store options and make a new client, I think we should have an always-set "header context propagator" that extracts the headers from a known key in the context, and just call something like cl.UpdateWorkflow(ContextWithHeaders(updateStartOpts.Headers), ... where ContextWithHeaders creates a context with that key if there are any headers.
cretz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing I noticed while reviewing concerning how payload data is represented. I will also see about getting a CLI team member here to review/approve.
internal/temporalcli/client.go
Outdated
|
|
||
| type headerPropagator struct{} | ||
|
|
||
| const cliHeaderContextKey = "worflow-headers" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const cliHeaderContextKey = "worflow-headers" | |
| const cliHeaderContextKey = "workflow-headers" |
Or better:
| const cliHeaderContextKey = "worflow-headers" | |
| type cliHeaderContextKey struct{} |
And use the empty struct when accessing
internal/temporalcli/client.go
Outdated
| val := ctx.Value(cliHeaderContextKey) | ||
| if headers, ok := val.(map[string]string); ok { | ||
| for k, v := range headers { | ||
| writer.Set(k, payload.EncodeString(v)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrmm, in addition to not wanting to use server utilities in here, I think this may need to be raw data. A user should be able to provide foo="var" or foo=1 and not have the latter become foo="1". They should be able to provide foo={"bar": "baz"}. This is the same approach that is taken everywhere else that accepts payloads, like for --search-attribute and --memo, can we match those (i.e. use stringKeysJSONValues)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, implemented this.
cretz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Will let CLI team review.
|
Can you add a test for this change? You should be able to do something like this (heavy pseudocode): res := s.Execute("workflow", "start", ..., "--headers", "someHeader=123",...)
s.Client.GetWorkflowHistory(...)
startedEvent := <first enums.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED eventType>
headers := startedEvent.GetWorkflowExecutionStartedEventAttributes().GetHeaders()
require.Equal(t, headers.Get("someHeader"), "123")that's not perfect by any means but that's the gist of what a test for this should look like. |
Done @spkane31 |
What was changed
Support setting of Temporal headers in workflows
Why?
The cli doesn't support the setting of workflow headers. With this change we would be able to pass the headers to Workflows using cli.
Checklist
Closes - [Feature Request] Allow setting Temporal headers when starting workflow #876
How was this tested:
temporal server start-dev--headersflag to start a workflow. Checked in Temporal UI, the Header section shows the headers set in Workflow.https://docs.temporal.io/cli/workflow