Skip to content
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

Option array type #26

Open
brad-jones opened this issue Mar 14, 2018 · 1 comment
Open

Option array type #26

brad-jones opened this issue Mar 14, 2018 · 1 comment

Comments

@brad-jones
Copy link

Thoughts on adding a new array option type. Which would then be an array of one of the existing types.

Given the following example task definition:

run-p:
  private: true
  usage: Parallel execution helper task
  options:
    commands:
      type: string
      required: true
    jobs:
      type: string
      default: 100%
  run: |
    parallel \
      --jobs ${jobs} \
      --keep-order \
      --line-buffer \
      --halt now,fail=1 \
      {} ::: ${commands}

And an example of how I am using it:

foo:
  usage: Runs some things in parallel
  run:
    task:
      name: run-p
      options:
        commands: '
          "ping -c 4 8.8.8.8"
          "ping -c 4 8.8.4.4"
        '

While this works and does the job for now, it would be nice if I could supply an array of strings to the task like this:

foo:
  usage: Runs some things in parallel
  run:
    task:
      name: run-p
      options:
        commands:
          - ping -c 4 8.8.8.8
          - ping -c 4 8.8.4.4

And then an example of what the run-p task definition might look like:

run-p:
  private: true
  usage: Parallel execution helper task
  options:
    commands:
      type: array
      required: true
      element-type: string
      delimiter: ","
    jobs:
      type: string
      default: 100%
  run: |
    parallel \
      --jobs ${jobs} \
      --keep-order \
      --line-buffer \
      --halt now,fail=1 \
      {} ::: \"$(X="${commands}"; echo $${X//,/\" \"})\"
@smyrman
Copy link

smyrman commented Jun 20, 2019

I know Terraform variable types where recently changed to allow the type-statement to state list(<element-type>) or map(<element-type>). That syntax also allows nesting deeper when/if that's desirable.

E.g. list(map(string)) -> go type []map[string]string (or indeed []interface{} with map[string]interface{} values).

Initially, one could/should restrict the allowed element types to primitive types, but it might be useful for the design not to exclude deep nesting possibilities, at least not for the case of tasks calling (internal) tasks.

Just to make the design task more difficult;-)


The following is meant as input to a design only:

Things to think about:

  • Calling a task from CLI with a collection type parameter (parse go type from string)
  • Calling a task from another task with a collection type parameter (pass-along parsed go type)
  • Parsing of lists v.s. parsing of other collection types from string (e.g. maps)

I really like the delimiter parsing for lists/arrays of primitive types. Parsing maps by delimiter, could be solved with a delimiter as well, e.g. = for key values and , to separate values (foo=a,bar=b). Nested types gets really tricky though, and not really easy to work with using delimiters alone.

E.g. consider map(list(string)), a plausible value would be foo=a,b,c,bar=a,b,c. It's not completely trivial to see when the map value ends, and the next key begins. Lists of lists would be equally problematic. list(list(string)), a,b,c,a,b,c. When do one list start and the other begin? In this case, you either need separate delimiters per list, or you need to rely on something more structured, such a custom DSL or JSON.

There could be cases where one want to pass JSON, or some other structured format, but I want to argue that this is out of scope.

Why? I think the best case for passing in JSON, is when you are doing it as part of som tooling pipeline, and then it's probably better to just parse everything as JSON, (possibly even via STDIN):
To illustrate what i mean:

The normal CLI method (with tab completion etc.):

tusk mytask --mystring=hello --mylist=1,2,3 arg1 arg2

An alternate method intended to tooling pipelines (delimiter configurations ignored):

tusk --json-pipe

STDIN content:

{
    "task": "hello",
    "options" {"mystring": "hello", "mylist": [1,2,3]},
    "args": ["arg1", "arg2"]
}

Example use-case for something like this, would be to use a tusk file as a Terraform external data source.

Not suggesting this is the actual syntax for JSON input. If JSON input (from stdin or elsewhere) is desired, it should be raised as a separate issue and discussed there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants