Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lucasmagalhaes/ics-ans-role-conda
  • alexthibault-ferial/ics-ans-role-conda
  • andersharrisson/ics-ans-role-conda
  • roryclarke/ics-ans-role-conda
  • rosselliot/ics-ans-role-conda
  • ics-ansible-galaxy/ics-ans-role-conda
6 results
Show changes
Commits on Source (58)
Showing
with 1030 additions and 48 deletions
exclude_paths:
- molecule/default/create.yml
- molecule/default/test_conda.yml
- molecule/default/test_conda_env.yml
skip_list:
- '602'
- '204'
- '208'
- '106'
[flake8]
ignore = E501
ignore = E501,W503,E203,E402
......@@ -5,3 +5,6 @@
.DS_Store
__pycache__
*.pyc
.mypy_cache
.vscode
.pytest_cache
---
include: 'https://gitlab.esss.lu.se/ics-infrastructure/gitlab-ci-yml/raw/master/Molecule.gitlab-ci.yml'
run_molecule:
tags:
- $RUNNER_TAG
parallel:
matrix:
- SCENARIO: default
RUNNER_TAG: molecule
- SCENARIO: debian
RUNNER_TAG: molecule
- SCENARIO: ubuntu
RUNNER_TAG: ubuntu_2204
- SCENARIO: ess-linux
RUNNER_TAG: molecule
script:
- molecule test --scenario-name $SCENARIO
---
extends: default
rules:
......
# ics-ans-role-conda
Ansible role to install conda on CentOS.
Ansible role to install `conda` on CentOS and Debian.
`mamba` is also installed by default.
## Requirements
This role includes as well:
- ansible >= 2.7
- molecule >= 2.20
- a `conda` module that can be used to manage conda packages.
- a `conda_env` module that can be used to manage conda environments.
## Role Variables
```yaml
conda_version: 4.6.12
conda_channel_alias: https://artifactory.esss.lu.se/artifactory/api/conda
# List of conda channels to use
conda_channels:
- ics-conda
- conda-forge
- anaconda-main
# List of conda environment yaml files to create
conda_env_files: []
```
See [defaults/main.yml](defaults/main.yml)
The role can create conda environments if you pass a list of yaml environment files via
the `conda_env_files` variable.
......@@ -31,6 +22,90 @@ conda_env_files:
- https://gitlab.esss.lu.se/ics-infrastructure/conda-environments/raw/master/molecule_env.yml
```
Note that this is deprecated as it has some drawbacks:
- the update is only based on the file content (via a handler) and not the environment itself
- handler can't be used when using `include_role`
Using the `conda_env` module is the recommended way.
## conda module
The `conda` module allows to install, update or remove conda packages.
`mamba` is used by default. Set `use_mamba: false` to use `conda` instead.
```yaml
- name: install flask 1.0 and Python 3.7
conda:
name:
- python=3.7
- flask=1.0
state: present
environment: myapp
- name: install flask from conda-forge
conda:
name: flask
state: present
environment: flaskapp
channels:
- conda-forge
- name: update flask to the latest version
conda:
name: flask
state: latest
environment: myapp
- name: update conda to the latest version
conda:
name: conda
state: latest
- name: remove flask from myapp environment
conda:
name: flask
state: absent
environment: myapp
```
## conda_env module
The `conda_env` module allows to create, update or remove conda environments.
Using `mamba` with this module isn't supported yet.
```yaml
- name: create myenv environment
conda_env:
name: myenv
state: present
file: /tmp/environment.yml
- name: update all packages in myenv environment
conda_env:
name: myenv
state: latest
- name: update myenv environment based on environment.yml
conda_env:
name: myenv
state: present
prune: true
file: /tmp/environment.yml
- name: force the environment creation (remove previous one first)
conda_env:
state: present
force: true
file: /tmp/environment.yml
- name: remove myenv environment
conda_env:
name: myenv
state: absent
```
Note that the environment.yml file shall be present locally on the host.
## Example Playbook
......
---
conda_version: 4.6.12
conda_python_version: 3.10.13
conda_version: 23.11.0
conda_mamba_version: 1.5.5
conda_owner: root
conda_group: root
conda_channel_alias: https://artifactory.esss.lu.se/artifactory/api/conda
# List of conda channels to use
conda_channels:
- ics-conda
- conda-e3
- ics-conda-forge
- conda-forge
- anaconda-main
# List of conda environment yaml files to create
conda_env_files: []
# Name of the conda environment to activate by default
# If left empty no conda env is activated
conda_default_env: ""
conda_use_only_tar_bz2: false
---
- name: create conda environment
command: "/opt/conda/bin/conda env create --force -f {{ env_file_path }}"
#!/usr/bin/python
# Copyright: (c) 2019, Benjamin Bertrand <beenje@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.1",
"status": ["preview"],
"supported_by": "community",
}
DOCUMENTATION = """
---
module: conda
short_description: Manages I(conda) packages
version_added: "2.9"
description:
- Install, update, remove packages with the I(conda) package manager.
- This module requires conda to be already installed.
- The minimum conda version required is 4.6.
options:
name:
description:
- A package name or package specification, like C(name=1.0).
- The package specification is only accepted with state=present.
- For state=latest or state=absent, use package name only.
- Accept a list of packages as well.
required: true
type: list
state:
description:
- Wether to install (C(present)), update (C(latest)) or remove (C(absent)) packages
- C(present) will ensure that the given packages are installed
- C(latest) will update the given packages to the latest available version
- C(absent) will remove the specified packages
- If the environment doesn't exist, it will be created.
choices: [ absent, latest, present ]
default: present
type: str
environment:
description:
- Environment name or full path.
- For example C(python3) or C(/opt/conda/envs/python3).
default: base
type: str
executable:
description:
- Full path of the conda or mamba command to use, like C(/home/conda/bin/conda).
- If not specified, C(conda) will be searched in the PATH as well as
the /opt/conda/bin directory.
type: path
use_mamba:
description:
- Use C(mamba) instead of C(conda)
default: True
type: bool
channels:
description:
- List of extra channels to use when installing packages.
type: list
requirements:
- conda >= 4.6
author:
- Benjamin Bertrand (@beenje)
"""
EXAMPLES = """
- name: install flask 1.0 and Python 3.7
conda:
name:
- python=3.7
- flask=1.0
state: present
environment: myapp
- name: install flask from conda-forge
conda:
name: flask
state: present
environment: flaskapp
channels:
- conda-forge
- name: update flask to the latest version
conda:
name: flask
state: latest
environment: myapp
- name: update conda to the latest version
conda:
name: conda
state: latest
- name: remove flask from myapp environment
conda:
name: flask
state: absent
environment: myapp
"""
RETURN = """
cmd:
description: The conda command that was run
type: list
returned: always
rc:
description: The return code of the command
type: int
returned: always
stdout_json:
description: The json output of the command
type: dict
returned: always
stderr:
description: The standard error of the command
type: str
returned: always
"""
import json
import os
from collections import namedtuple
from ansible.module_utils.basic import AnsibleModule
Result = namedtuple("Result", "changed cmd rc stdout_json stderr")
class Conda:
"""Class to perform conda operations"""
def __init__(
self, module, environment, executable=None, use_mamba=False, channels=None, check_mode=False
):
self.module = module
if use_mamba:
exe = "mamba"
else:
exe = "conda"
self.executable = executable or module.get_bin_path(
exe, required=True, opt_dirs=["/opt/conda/bin"]
)
if environment is None:
self.env_args = []
else:
if os.path.sep in environment:
env_flag = "--prefix"
else:
env_flag = "--name"
self.env_args = [env_flag, environment]
self.default_args = ["-y"] + self.env_args
if channels:
for channel in channels:
self.default_args.extend(["--channel", channel])
if check_mode:
self.default_args.append("--dry-run")
@staticmethod
def changed(stdout_json):
"""Return True if any change was performed by the conda command"""
# When conda didn't install/update anything, the output is:
# {
# "message": "All requested packages already installed.",
# "success": true
# }
# When conda has some operations to perform, the list of actions
# is returned in the json output:
# {
# "actions": {
# "FETCH": [],
# "LINK": [
# {
# "base_url": "https://repo.anaconda.com/pkgs/main",
# "build_number": 0,
# "build_string": "py_0",
# "channel": "pkgs/main",
# "dist_name": "flask-1.1.1-py_0",
# "name": "flask",
# "platform": "noarch",
# "version": "1.1.1"
# }
# ],
# "PREFIX": "/opt/conda/envs/python3"
# },
# "prefix": "/opt/conda/envs/python3",
# "success": true
# }
if "actions" not in stdout_json:
return False
return True
def run_conda(self, cmd, *args, **kwargs):
"""Run a conda commmand"""
fail_on_error = kwargs.pop("fail_on_error", True)
subcmd = kwargs.pop("subcmd", None)
if subcmd is None:
command = [self.executable]
else:
command = [self.executable, subcmd]
command.extend([cmd, "--quiet", "--json"])
command.extend(args)
rc, stdout, stderr = self.module.run_command(command)
if fail_on_error and rc != 0:
self.module.fail_json(
command=command,
msg="Command failed",
rc=rc,
stdout=stdout,
stderr=stderr,
)
try:
stdout_json = json.loads(stdout)
except ValueError:
if cmd == "remove":
# conda remove --all doesn't output anything on stdout if the
# environment doesn't exist (in 4.7.12)
if stdout.strip() == "":
return Result(False, command, rc, {}, stderr)
self.module.fail_json(
command=command,
msg="Failed to parse the output of the command",
stdout=stdout,
stderr=stderr,
)
return Result(self.changed(stdout_json), command, rc, stdout_json, stderr)
def list_packages(self):
"""Return the list of packages name installed in the environment"""
result = self.run_conda("list", *self.env_args)
return [pkg["name"] for pkg in result.stdout_json]
def env_exists(self):
"""Return True if the environment exists
The existence is checked by running the conda list -n/-p environment command.
"""
result = self.run_conda("list", *self.env_args, fail_on_error=False)
return result.rc == 0
def install(self, packages):
"""Install the given conda packages"""
args = self.default_args + packages
return self.run_conda("install", "-S", *args)
def update(self, packages):
"""Update the given conda packages"""
args = self.default_args + packages
return self.run_conda("update", *args)
def update_all(self):
"""Update all packages in the environment"""
return self.run_conda("update", "--all", *self.env_args)
def create(self, packages):
"""Create a new environment with the given conda packages"""
args = self.default_args + packages
return self.run_conda("create", *args)
def remove(self, packages):
"""Remove the conda packages from the environment"""
installed_packages = self.list_packages()
# clean the packages name by removing the version spec
# to keep only the package name in lowercase
packages_names = [pkg.split("=")[0].lower() for pkg in packages]
packages_to_remove = set(installed_packages) & set(packages_names)
if packages_to_remove:
args = self.default_args + list(packages_to_remove)
return self.run_conda("remove", *args)
else:
# None of the given packages are in the environment
# Nothing to do
return Result(False, "", 0, {}, "")
def env_update(self, file, prune=False):
"""Create or update the environment based on file"""
args = ["-f", file] + self.env_args
if prune:
args.append("--prune")
return self.run_conda("update", subcmd="env", *args)
def env_create(self, file, force=False):
"""Create the environment based on file"""
args = ["-f", file] + self.env_args
if force:
args.append("--force")
return self.run_conda("create", subcmd="env", *args)
def env_remove(self):
"""Remove the given environment"""
return self.run_conda("remove", "--all", *self.env_args)
def run_module():
module_args = dict(
name=dict(type="list", required=True),
state=dict(choices=["present", "absent", "latest"], default="present"),
executable=dict(type="path"),
use_mamba=dict(type="bool", default=True),
environment=dict(type="str", default="base"),
channels=dict(type="list", default=[]),
)
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
state = module.params["state"]
packages = module.params["name"]
conda = Conda(
module,
environment=module.params["environment"],
executable=module.params["executable"],
use_mamba=module.params["use_mamba"],
channels=module.params["channels"],
check_mode=module.check_mode,
)
if state == "present":
if conda.env_exists():
result = conda.install(packages)
else:
result = conda.create(packages)
elif state == "latest":
if conda.env_exists():
result = conda.update(packages)
else:
result = conda.create(packages)
elif state == "absent":
result = conda.remove(packages)
module.exit_json(**result._asdict())
def main():
run_module()
if __name__ == "__main__":
main()
#!/usr/bin/python
# Copyright: (c) 2019, Benjamin Bertrand <beenje@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.1",
"status": ["preview"],
"supported_by": "community",
}
DOCUMENTATION = """
---
module: conda_env
short_description: Manages I(conda) environment
version_added: "2.9"
description:
- Create, update, remove I(conda) environments.
- This module requires conda to be already installed.
- The minimum conda version required is 4.7.12.
options:
name:
description:
- The name or full path of the environment. Override the name in the environment.yml file if defined.
required: false
type: str
state:
description:
- Wether to create (C(present)), update (C(latest)) or remove (C(absent)) the environment
- C(present) will ensure that the given environment exits and matches the environment.yml file.
- C(latest) will update all packages in the environment. It is exclusive with file.
- C(absent) will remove the specified environment.
- If the environment doesn't exist, it will be created.
choices: [ absent, latest, present ]
default: present
type: str
file:
description:
- The path to a conda environment.yml file, which should be local to the remote system.
type: path
executable:
description:
- Full path of the conda command to use, like C(/home/conda/bin/conda).
- If not specified, C(conda) will be searched in the PATH as well as
the /opt/conda/bin directory.
type: path
prune:
description:
- Remove installed packages not defined in environment.yml. Can only be used with state c(present).
type: bool
force:
description:
- Force the creation of an environment by first removing a previously existing environment of the same name.
Can only be used with state c(present).
type: bool
requirements:
- conda >= 4.7.12
author:
- Benjamin Bertrand (@beenje)
"""
EXAMPLES = """
- name: create myenv environment
conda_env:
name: myenv
state: present
file: /tmp/environment.yml
- name: update all packages in myenv environment
conda_env:
name: myenv
state: latest
- name: update myenv environment based on environment.yml
conda_env:
name: myenv
state: present
prune: true
file: /tmp/environment.yml
- name: force the environment creation (remove previous one first)
conda_env:
state: present
force: true
file: /tmp/environment.yml
- name: remove myenv environment
conda_env:
name: myenv
state: absent
"""
RETURN = """
cmd:
description: The conda command that was run
type: list
returned: always
rc:
description: The return code of the command
type: int
returned: always
stdout_json:
description: The json output of the command
type: dict
returned: always
stderr:
description: The standard error of the command
type: str
returned: always
"""
import json
import os
from collections import namedtuple
from ansible.module_utils.basic import AnsibleModule
Result = namedtuple("Result", "changed cmd rc stdout_json stderr")
class Conda:
"""Class to perform conda operations"""
def __init__(
self, module, environment, executable=None, channels=None, check_mode=False
):
self.module = module
self.executable = executable or module.get_bin_path(
"conda", required=True, opt_dirs=["/opt/conda/bin"]
)
if environment is None:
self.env_args = []
else:
if os.path.sep in environment:
env_flag = "--prefix"
else:
env_flag = "--name"
self.env_args = [env_flag, environment]
self.default_args = ["-y"] + self.env_args
if channels:
for channel in channels:
self.default_args.extend(["--channel", channel])
if check_mode:
self.default_args.append("--dry-run")
@staticmethod
def changed(stdout_json):
"""Return True if any change was performed by the conda command"""
# When conda didn't install/update anything, the output is:
# {
# "message": "All requested packages already installed.",
# "success": true
# }
# When conda has some operations to perform, the list of actions
# is returned in the json output:
# {
# "actions": {
# "FETCH": [],
# "LINK": [
# {
# "base_url": "https://repo.anaconda.com/pkgs/main",
# "build_number": 0,
# "build_string": "py_0",
# "channel": "pkgs/main",
# "dist_name": "flask-1.1.1-py_0",
# "name": "flask",
# "platform": "noarch",
# "version": "1.1.1"
# }
# ],
# "PREFIX": "/opt/conda/envs/python3"
# },
# "prefix": "/opt/conda/envs/python3",
# "success": true
# }
if "actions" not in stdout_json:
return False
return True
def run_conda(self, cmd, *args, **kwargs):
"""Run a conda commmand"""
fail_on_error = kwargs.pop("fail_on_error", True)
subcmd = kwargs.pop("subcmd", None)
if subcmd is None:
command = [self.executable]
else:
command = [self.executable, subcmd]
command.extend([cmd, "--quiet", "--json"])
command.extend(args)
rc, stdout, stderr = self.module.run_command(command)
if fail_on_error and rc != 0:
self.module.fail_json(
command=command,
msg="Command failed",
rc=rc,
stdout=stdout,
stderr=stderr,
)
try:
stdout_json = json.loads(stdout)
except ValueError:
if cmd == "remove":
# conda remove --all doesn't output anything on stdout if the
# environment doesn't exist (in 4.7.12)
if stdout.strip() == "":
return Result(False, command, rc, {}, stderr)
self.module.fail_json(
command=command,
msg="Failed to parse the output of the command",
stdout=stdout,
stderr=stderr,
)
return Result(self.changed(stdout_json), command, rc, stdout_json, stderr)
def list_packages(self):
"""Return the list of packages name installed in the environment"""
result = self.run_conda("list", *self.env_args)
return [pkg["name"] for pkg in result.stdout_json]
def env_exists(self):
"""Return True if the environment exists
The existence is checked by running the conda list -n/-p environment command.
"""
result = self.run_conda("list", *self.env_args, fail_on_error=False)
return result.rc == 0
def install(self, packages):
"""Install the given conda packages"""
args = self.default_args + packages
return self.run_conda("install", "-S", *args)
def update(self, packages):
"""Update the given conda packages"""
args = self.default_args + packages
return self.run_conda("update", *args)
def update_all(self):
"""Update all packages in the environment"""
return self.run_conda("update", "--all", *self.env_args)
def create(self, packages):
"""Create a new environment with the given conda packages"""
args = self.default_args + packages
return self.run_conda("create", *args)
def remove(self, packages):
"""Remove the conda packages from the environment"""
installed_packages = self.list_packages()
# clean the packages name by removing the version spec
# to keep only the package name in lowercase
packages_names = [pkg.split("=")[0].lower() for pkg in packages]
packages_to_remove = set(installed_packages) & set(packages_names)
if packages_to_remove:
args = self.default_args + list(packages_to_remove)
return self.run_conda("remove", *args)
else:
# None of the given packages are in the environment
# Nothing to do
return Result(False, "", 0, {}, "")
def env_update(self, file, prune=False):
"""Create or update the environment based on file"""
args = ["-f", file] + self.env_args
if prune:
args.append("--prune")
return self.run_conda("update", subcmd="env", *args)
def env_create(self, file, force=False):
"""Create the environment based on file"""
args = ["-f", file] + self.env_args
if force:
args.append("--force")
return self.run_conda("create", subcmd="env", *args)
def env_remove(self):
"""Remove the given environment"""
return self.run_conda("remove", "--all", *self.env_args)
def run_module():
module_args = dict(
name=dict(type="str"),
state=dict(choices=["present", "absent", "latest"], default="present"),
executable=dict(type="path"),
file=dict(type="path"),
prune=dict(type="bool", default=False),
force=dict(type="bool", default=False),
)
module = AnsibleModule(
argument_spec=module_args,
required_one_of=[["name", "file"]],
required_if=([("state", "absent", ["name"]), ("state", "latest", ["name"])]),
supports_check_mode=False,
)
state = module.params["state"]
conda = Conda(
module,
environment=module.params["name"],
executable=module.params["executable"],
)
if state == "present":
if module.params["force"]:
result = conda.env_create(module.params["file"], module.params["force"])
else:
result = conda.env_update(module.params["file"], module.params["prune"])
elif state == "latest":
result = conda.update_all()
elif state == "absent":
result = conda.env_remove()
module.exit_json(**result._asdict())
def main():
run_module()
if __name__ == "__main__":
main()
......@@ -9,6 +9,9 @@ galaxy_info:
- name: CentOS
versions:
- 7
- name: Debian
versions:
- 9
dependencies: []
# List your role dependencies here, one per line.
# Be sure to remove the '[]' above if you add dependencies
......
---
dependency:
name: galaxy
lint: |
set -e
yamllint .
ansible-lint
flake8
provisioner:
name: ansible
playbooks:
converge: ../default/converge.yml
config_options:
defaults:
callback_whitelist: profile_tasks
gather_timeout: 20
scenario:
name: debian
verifier:
name: testinfra
directory: ../default/tests/
driver:
name: docker
platforms:
- name: ics-ans-role-conda-debian10
image: debian:10
- name: ics-ans-role-conda-debian11
image: debian:11
- name: ics-ans-role-conda-debian12
image: debian:12
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python2-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi
---
name: myenv1
channels:
- conda-forge
dependencies:
- python=3.7.1
---
name: myenv2
channels:
- conda-forge
dependencies:
- python=3.7.3
---
dependency:
name: galaxy
lint:
name: yamllint
lint: |
set -e
yamllint .
ansible-lint
flake8
provisioner:
name: ansible
lint:
name: ansible-lint
config_options:
defaults:
callback_whitelist: profile_tasks
gather_timeout: 20
inventory:
host_vars:
ics-ans-role-conda-create-env:
group_vars:
conda_create_env:
conda_env_files:
- "{{ playbook_dir }}/tests/python36_env.yml"
- https://gitlab.esss.lu.se/ics-ansible-galaxy/ics-ans-role-conda/raw/master/molecule/default/tests/python27_env.yml
ics-ans-role-conda-rpm:
conda_default_env: python36
conda_owner: vagrant
conda_group: vagrant
conda_rpm:
conda_channels:
- conda-forge
scenario:
name: default
verifier:
name: testinfra
lint:
name: flake8
driver:
name: docker
platforms:
......@@ -29,5 +35,9 @@ platforms:
image: centos:7
- name: ics-ans-role-conda-create-env
image: centos:7
groups:
- conda_create_env
- name: ics-ans-role-conda-rpm
image: centos:7
groups:
- conda_rpm
---
- name: Prepare
hosts: ics-ans-role-conda-rpm
gather_facts: false
- name: Prepare ics-ans-role-conda-rpm
hosts: ics-ans-role-conda-rpm*
gather_facts: true
tasks:
- name: install conda rpm
yum:
......@@ -11,3 +11,18 @@
file:
path: /opt/conda/.condarc
state: touch
- name: Add additional packages for ESS Linux
hosts: ics-ans-role-conda-create-env-ess-linux
tasks:
- name: install python3-terminal
yum:
name: python3-terminal
state: present
- name: Prepare ics-ans-role-conda-create-env
hosts: ics-ans-role-conda-create-env*
gather_facts: false
tasks:
- name: create vagrant user
user:
name: vagrant
state: present
---
- name: Side Effect
hosts:
- ics-ans-role-conda-default
- ics-ans-role-conda-ess-linux
vars:
conda_path: /opt/conda
become: true
tasks:
- name: test conda module
include_tasks: test_conda.yml
- name: test conda_env module
include_tasks: test_conda_env.yml
---
- name: display conda version
command: "{{ conda_path }}/bin/conda --version"
register: conda_version
- name: make sure conda environments don't exist
file:
path: "{{ conda_path }}/envs/{{ item }}"
state: absent
loop:
- myapp
- python3
- condaforge
- name: try to install a package that doesn't exist
conda:
name: donotexist
state: present
register: donotexist_install
ignore_errors: true
- name: verify that the command failed
assert:
that:
- donotexist_install.failed
- name: install flask in myapp
conda:
name:
- Python=3.7
- flask
environment: myapp
register: flask_install
- name: verify we recorded a change
assert:
that:
- flask_install.changed
- name: verify that flask is installed
command: "{{ conda_path }}/envs/myapp/bin/flask --version"
- name: update flask in myapp
conda:
name: flask
state: latest
environment: myapp
register: flask_update
- name: verify we didn't record a change
assert:
that:
- not flask_update.changed
- name: remove flask from myapp
conda:
name: flask
state: absent
environment: myapp
register: flask_remove
- name: verify we recorded a change
assert:
that:
- flask_remove.changed
- name: verify that flask was removed
command: "{{ conda_path }}/envs/myapp/bin/flask --version"
register: flask_cmd
failed_when: "flask_cmd.rc == 0"
- name: try to remove flask again from myapp
conda:
name: flask
state: absent
environment: myapp
register: flask_remove2
- name: verify we didn't record a change
assert:
that:
- not flask_remove2.changed
- name: create an environment with Python 3.7.1
conda:
name: Python=3.7.1
environment: python3
register: python_install
- name: verify we recorded a change
assert:
that:
- python_install.changed
- name: check Python version
command: "{{ conda_path }}/envs/python3/bin/python --version"
register: python_version
- name: verify Python 3.7.1 was installed
assert:
that:
- "'Python 3.7.1' in python_version.stdout"
- name: update Python in python3 env
conda:
name: Python
state: latest
environment: python3
register: python_update
- name: verify we recorded a change
assert:
that:
- python_update.changed
- name: check Python version
command: "{{ conda_path }}/envs/python3/bin/python --version"
register: python_version
- name: verify Python was updated
assert:
that:
- "'Python 3.7.1' not in python_version.stdout"
- "'Python' in python_version.stdout"