cloudeteer / actions

☁️ Cloudeteer's GitHub Actions
https://www.cloudeteer.de
MIT License
1 stars 0 forks source link

Error on multiline condition at Terraform variable validation #4

Open rswrz opened 6 days ago

rswrz commented 6 days ago

Description

The main.py script fails when parsing a Terraform variable file containing a multi-line conditional in a variable validation block. The script works as expected with single-line conditionals but raises an error when the condition spans multiple lines.

Steps to Reproduce

  1. Setup virtual environment and install requirements

    $ pwd
    /home/debug/get-terraform-version
    
    $ virtualenv .
    $ source bin/activate
    $ pip install -r requirements.txt
  2. Create debug.tf file with single-line condition

    # debug.tf
    terraform {
      required_version = "1.0"
    }
    
    variable "debug" {
      validation {
        condition     = (false && !false) || (!false && false) || (!false && !false)
        error_message = "Debug"
      }
    }
  3. Run main.py successfully

    $ GITHUB_OUTPUT=/dev/stdout directory=. python main.py
    ::notice::Terraform version "1.0" found in "./debug.tf"
    Setting GitHub Actions output: required_version=1.0
    required_version=1.0
  4. Modify debug.tf to use a multi-line condition

    # debug.tf
    terraform {
      required_version = "1.0"
    }
    
    variable "debug" {
      validation {
        condition = (
          (false && !false)
          || (!false && false)
          || (!false && !false)
        )
        error_message = "Debug"
      }
    }
  5. Run main.py again, resulting in an error

    $ GITHUB_OUTPUT=/dev/stdout directory=. python main.py
    Traceback (most recent call last):
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser_state.py", line 77, in feed_token
        action, arg = states[state][token.type]
                      ~~~~~~~~~~~~~^^^^^^^^^^^^
    KeyError: '__ANON_9'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/Volumes/Work/CDT/actions/get-terraform-version/main.py", line 41, in <module>
        required_version = get_required_version()
      File "/Volumes/Work/CDT/actions/get-terraform-version/main.py", line 13, in get_required_version
        conf = hcl2.load(file)
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/hcl2/api.py", line 14, in load
        return loads(file.read(), with_meta=with_meta)
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/hcl2/api.py", line 27, in loads
        tree = hcl2.parse(text + "\n")
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/lark.py", line 655, in parse
        return self.parser.parse(text, start=start, on_error=on_error)
               ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parser_frontends.py", line 104, in parse
        return self.parser.parse(stream, chosen_start, **kw)
               ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 42, in parse
        return self.parser.parse(lexer, start)
               ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 88, in parse
        return self.parse_from_state(parser_state)
               ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 111, in parse_from_state
        raise e
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 102, in parse_from_state
        state.feed_token(token)
        ~~~~~~~~~~~~~~~~^^^^^^^
      File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser_state.py", line 80, in feed_token
        raise UnexpectedToken(token, expected, state=self, interactive_parser=None)
    lark.exceptions.UnexpectedToken: Unexpected token Token('__ANON_9', '||') at line 10, column 7.
    Expected one of: 
            * RPAR

Expected Behavior

The script should parse and process the multi-line conditional as it does with a single-line conditional.

Actual Behavior

The script raises a lark.exceptions.UnexpectedToken error, failing to parse the multi-line conditional.

rswrz commented 6 days ago

I did a quick test on latest python-hcl package, which failes also with a slightly different error message:

python-hcl2==5.1.1
$ GITHUB_OUTPUT=/dev/stdout directory=. python main.py
Traceback (most recent call last):
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser_state.py", line 77, in feed_token
    action, arg = states[state][token.type]
                  ~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'BINARY_OP'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Volumes/Work/CDT/actions/get-terraform-version/main.py", line 41, in <module>
    required_version = get_required_version()
  File "/Volumes/Work/CDT/actions/get-terraform-version/main.py", line 13, in get_required_version
    conf = hcl2.load(file)
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/hcl2/api.py", line 15, in load
    return loads(file.read(), with_meta=with_meta)
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/hcl2/api.py", line 28, in loads
    tree = hcl2.parse(text + "\n")
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/lark.py", line 655, in parse
    return self.parser.parse(text, start=start, on_error=on_error)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parser_frontends.py", line 104, in parse
    return self.parser.parse(stream, chosen_start, **kw)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 42, in parse
    return self.parser.parse(lexer, start)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 88, in parse
    return self.parse_from_state(parser_state)
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 111, in parse_from_state
    raise e
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser.py", line 102, in parse_from_state
    state.feed_token(token)
    ~~~~~~~~~~~~~~~~^^^^^^^
  File "/Volumes/Work/CDT/actions/get-terraform-version/lib/python3.13/site-packages/lark/parsers/lalr_parser_state.py", line 80, in feed_token
    raise UnexpectedToken(token, expected, state=self, interactive_parser=None)
lark.exceptions.UnexpectedToken: Unexpected token Token('BINARY_OP', '||') at line 10, column 7.
Expected one of: 
        * RPAR
rswrz commented 6 days ago

Using the following debug.tf file, where || is used at the end of each line, it does not fail:

# debug.tf
terraform {
  required_version = "1.0"
}

variable "debug" {
  validation {
    condition = (
      (false && !false) ||
      (!false && false) ||
      (!false && !false)
    )
    error_message = "Debug"
  }
}