AnsibleError: No filter named "to_env"

Hello,
I’m trying to get trellis to deploy to my staging server (a digital ocean box) and I’m getting an error in the “Copy Project templates” task:

failed: [xxx.xxx.xxx.xxx (item={u'dest': u'.env', u'src': u'roles/deploy/templates/env.j2', u'name': u'.env config'}) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": {
        "dest": ".env",
        "name": ".env config",
        "src": "roles/deploy/templates/env.j2"
    },
    "msg": "AnsibleError: template error while templating string: no filter named 'to_env'. String: {{ site_env | to_env }}\r\n"
}

Something is probably quite wrong if that filter can’t be found. Do you know what version of Trellis you’re using?

Does this file exist? trellis/filters.py at 68cbc413587265c4b9500ea68563923185d64afe · roots/trellis · GitHub

Does your ansible.cfg file (in Trellis dir) have a line like this? https://github.com/roots/trellis/blob/68cbc413587265c4b9500ea68563923185d64afe/ansible.cfg#L3

Yes, both of those files exist in those locations with those contents.

I am using 1.20.1

We’re going to need a lot more details about your project + setup:

  1. OS + version
  2. Vagrant details
  3. Command you ran (I assume trellis deploy staging?)
  4. Can you paste your galaxy.yml?
  5. Any major changes/modifications you’ve made?
  6. Has this command previously worked?
  7. Run the command again and supply the full log output (minus anything redacted)

Thanks

Sure.

  • I’m running Mac OS 13.1
  • I’m not using vagrant (I’ve had consistent issues with Parallels network config) so locally I’m running larvel valet pointed to the site/web directory and then run composer commands in the site directory

If I run ansible-playbook deploy.yml -vvv -e "site=example.com env=staging" -i hosts/staging I get this output:

TASK [deploy : Copy project templates] *************************************************************************************************************************************************************************************************
task path: /Users/user/example.com/trellis/roles/deploy/tasks/build.yml:17
<xxx.xxx.xxx.xxx> ESTABLISH SSH CONNECTION FOR USER: web
<xxx.xxx.xxx.xxx> SSH: EXEC ssh -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o HostKeyAlgorithms=ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="web"' -o ConnectTimeout=10 -o 'ControlPath="/Users/user/.ansible/cp/cb9dacd761"' 142.93.204.216 '/bin/sh -c '"'"'echo ~web && sleep 0'"'"''
<xxx.xxx.xxx.xxx> (0, b'/home/web\n', b'')
<xxx.xxx.xxx.xxx> ESTABLISH SSH CONNECTION FOR USER: web
<xxx.xxx.xxx.xxx> SSH: EXEC ssh -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o HostKeyAlgorithms=ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="web"' -o ConnectTimeout=10 -o 'ControlPath="/Users/user/.ansible/cp/cb9dacd761"' XXX.XXX.XXX.XXX '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/web/.ansible/tmp `"&& mkdir "` echo /home/web/.ansible/tmp/ansible-tmp-1679334729.948027-38438-1946855422152 `" && echo ansible-tmp-1679334729.948027-38438-1946855422152="` echo /home/web/.ansible/tmp/ansible-tmp-1679334729.948027-38438-1946855422152 `" ) && sleep 0'"'"''
<xxx.xxx.xxx.xxx> (0, b'ansible-tmp-1679334729.948027-38438-1946855422152=/home/web/.ansible/tmp/ansible-tmp-1679334729.948027-38438-1946855422152\n', b'')
<xxx.xxx.xxx.xxx> ESTABLISH SSH CONNECTION FOR USER: web
<xxx.xxx.xxx.xxx> SSH: EXEC ssh -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o HostKeyAlgorithms=ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="web"' -o ConnectTimeout=10 -o 'ControlPath="/Users/user/.ansible/cp/cb9dacd761"' 142.93.204.216 '/bin/sh -c '"'"'rm -f -r /home/web/.ansible/tmp/ansible-tmp-1679334729.948027-38438-1946855422152/ > /dev/null 2>&1 && sleep 0'"'"''
<xxx.xxx.xxx.xxx> (0, b'', b'')
The full traceback is:
Traceback (most recent call last):
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/ansible/template/__init__.py", line 445, in __getitem__
    func = self._delegatee[key]
           ~~~~~~~~~~~~~~~^^^^^
KeyError: 'to_env'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/ansible/template/__init__.py", line 952, in do_template
    t = myenv.from_string(data)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/jinja2/environment.py", line 1105, in from_string
    return cls.from_code(self, self.compile(source), gs, None)
                               ^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/jinja2/environment.py", line 768, in compile
    self.handle_exception(source=source_hint)
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<unknown>", line 1, in template
jinja2.exceptions.TemplateSyntaxError: Could not load "to_env": 'to_env'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/ansible/plugins/action/template.py", line 137, in run
    resultant = templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/ansible/template/__init__.py", line 954, in do_template
    raise AnsibleError("template error while templating string: %s. String: %s" % (to_native(e), to_native(data)), orig_exc=e)
ansible.errors.AnsibleError: template error while templating string: Could not load "to_env": 'to_env'. String: {{ site_env | to_env }}
. Could not load "to_env": 'to_env'
failed: [xxx.xxx.xxx.xxx] (item=.env config) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": {
        "dest": ".env",
        "mode": "0600",
        "name": ".env config",
        "src": "roles/deploy/templates/env.j2"
    },
    "msg": "AnsibleError: template error while templating string: Could not load \"to_env\": 'to_env'. String: {{ site_env | to_env }}\n. Could not load \"to_env\": 'to_env'"
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
XXX.XXX.XXX.XXX             : ok=11   changed=3    unreachable=0    failed=1    skipped=24   rescued=0    ignored=0   
localhost                  : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

You didn’t answer a few of those questions, but there’s one more important one I forgot:

  • Run ansible-playbook --version and paste the results please

Any reason you aren’t using trellis-cli? I’d be interested if you ran trellis init in your project to install dependencies, and then trellis deploy staging what the results would be.

ansible-playbook [core 2.14.1]
  config file = /Users/user/example.com/trellis/ansible.cfg
  configured module search path = ['/Users/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/homebrew/Cellar/ansible/7.1.0/libexec/lib/python3.11/site-packages/ansible
  ansible collection location = /Users/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /opt/homebrew/bin/ansible-playbook
  python version = 3.11.1 (main, Dec 23 2022, 09:28:24) [Clang 14.0.0 (clang-1400.0.29.202)] (/opt/homebrew/Cellar/ansible/7.1.0/libexec/bin/python3.11)
  jinja version = 3.1.2
  libyaml = True

My galaxy.yml:

---
roles:
  - name: composer
    src: geerlingguy.composer
    version: 1.9.0

  - name: ntp
    src: geerlingguy.ntp
    version: 2.3.1

  - name: logrotate
    src: nickhammond.logrotate
    version: v0.0.5

  - name: swapfile
    src: oefenweb.swapfile
    version: v2.0.36

  - name: mailpit
    src: roots.mailpit
    version: v1.0.0

I just started over with a fresh site trellis new in a new directory and now I’m not getting the error. (I did make some changes, so I just wanted to see if I can get this working fresh, then I can slowly re-introduce my changes)

My end goal is to hopefully use bitbucket CI/CD to deploy this. I setup ssh keys correctly to my server (on digital ocean) and here is my bitbucket-pipelines.yml file:

image: nikolaik/python-nodejs
options:
 max-time: 10
pipelines:
  branches:
    test:
      - step:
          name: Deploy to server
          caches:
            - pip
          script:
            - cd trellis
            - pip install -r requirements.txt
            - ansible-galaxy install -r galaxy.yml
            - ansible-playbook deploy.yml -vvv -e "site=testing.example.com env=staging" -i hosts/staging

And that’s the error I get:

TASK [deploy : Copy project templates] *****************************************
task path: /opt/atlassian/pipelines/agent/build/trellis/roles/deploy/tasks/build.yml:17
<XXX.XXX.XXX.XXX> ESTABLISH SSH CONNECTION FOR USER: web
<XXX.XXX.XXX.XXX> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="web"' -o ConnectTimeout=10 -o 'ControlPath="/root/.ansible/cp/cb9dacd761"' XXX.XXX.XXX.XXX '/bin/sh -c '"'"'echo ~web && sleep 0'"'"''
<XXX.XXX.XXX.XXX> (0, b'/home/web\n', b'')
<XXX.XXX.XXX.XXX> ESTABLISH SSH CONNECTION FOR USER: web
<XXX.XXX.XXX.XXX> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="web"' -o ConnectTimeout=10 -o 'ControlPath="/root/.ansible/cp/cb9dacd761"' XXX.XXX.XXX.XXX '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/web/.ansible/tmp `"&& mkdir "` echo /home/web/.ansible/tmp/ansible-tmp-1679335124.353757-287-194313047771109 `" && echo ansible-tmp-1679335124.353757-287-194313047771109="` echo /home/web/.ansible/tmp/ansible-tmp-1679335124.353757-287-194313047771109 `" ) && sleep 0'"'"''
<XXX.XXX.XXX.XXX> (0, b'ansible-tmp-1679335124.353757-287-194313047771109=/home/web/.ansible/tmp/ansible-tmp-1679335124.353757-287-194313047771109\n', b'')
<XXX.XXX.XXX.XXX> ESTABLISH SSH CONNECTION FOR USER: web
<XXX.XXX.XXX.XXX> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="web"' -o ConnectTimeout=10 -o 'ControlPath="/root/.ansible/cp/cb9dacd761"' 142.93.204.216 '/bin/sh -c '"'"'rm -f -r /home/web/.ansible/tmp/ansible-tmp-1679335124.353757-287-194313047771109/ > /dev/null 2>&1 && sleep 0'"'"''
<XXX.XXX.XXX.XXX> (0, b'', b'')
The full traceback is:
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/ansible/template/__init__.py", line 445, in __getitem__
    func = self._delegatee[key]
           ~~~~~~~~~~~~~~~^^^^^
KeyError: 'to_env'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/ansible/template/__init__.py", line 952, in do_template
    t = myenv.from_string(data)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 1105, in from_string
    return cls.from_code(self, self.compile(source), gs, None)
                               ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 768, in compile
    self.handle_exception(source=source_hint)
  File "/usr/local/lib/python3.11/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<unknown>", line 1, in template
jinja2.exceptions.TemplateSyntaxError: Could not load "to_env": 'to_env'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/ansible/plugins/action/template.py", line 141, in run
    resultant = templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/ansible/template/__init__.py", line 954, in do_template
    raise AnsibleError("template error while templating string: %s. String: %s" % (to_native(e), to_native(data)), orig_exc=e)
ansible.errors.AnsibleError: template error while templating string: Could not load "to_env": 'to_env'. String: {{ site_env | to_env }}
. Could not load "to_env": 'to_env'
failed: [XXX.XXX.XXX.XXX] (item=.env config) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": {
        "dest": ".env",
        "mode": "0600",
        "name": ".env config",
        "src": "roles/deploy/templates/env.j2"
    },
    "msg": "AnsibleError: template error while templating string: Could not load \"to_env\": 'to_env'. String: {{ site_env | to_env }}\n. Could not load \"to_env\": 'to_env'"
}
PLAY RECAP *********************************************************************
XXX.XXX.XXX.XXX             : ok=11   changed=3    unreachable=0    failed=1    skipped=24   rescued=0    ignored=0   
localhost                  : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

But running trellis deploy staging or running ansible-playbook deploy.yml -vvv -e "site=testing.example.com env=staging" -i hosts/staging both work fine.

So I guess my question is really more about how to get CI/CD working here…

So I got it working…I’m not exactly sure what I was doing wrong, but after starting fresh and re-setting up SSH it works now.

1 Like

Glad you got it working and for all the troubleshooting.

We do offer GitHub - roots/setup-trellis-cli: 👷 Sets up Trellis CLI for GitHub Action workflows for GitHub but nothing for bitbucket yet. Regardless, I’d still suggest on installing trellis-cli as part of the CI pipeline, then you’d end up with something like this:

- step:
    name: Install trellis-cli
    script:
      - curl -sL https://roots.io/trellis/cli/get | bash
- step:
    name: Deploy
    caches:
      - pip
    script:
      - trellis init
      - trellis galaxy install
      - trellis deploy staging