├── handlers └── main.yml ├── .yamllint.yaml ├── .config └── ansible-lint.yml ├── vars ├── default.yml ├── Darwin.yml ├── Archlinux.yml ├── Windows.yml └── main.yml ├── .gitignore ├── templates └── anaconda.sh.j2 ├── meta ├── requirements.yml └── main.yml ├── .github └── workflows │ └── build.yml ├── test.yml ├── platform-matrix-v1.json ├── tasks ├── main.yml ├── Windows.yml └── default.yml ├── dl-checksum.sh ├── LICENSE ├── README.md ├── library ├── LICENSE.txt └── conda.py └── defaults └── main.yml /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for anaconda 3 | -------------------------------------------------------------------------------- /.yamllint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | line-length: disable 4 | -------------------------------------------------------------------------------- /.config/ansible-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | skip_list: 3 | - 'name[template]' 4 | -------------------------------------------------------------------------------- /vars/default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | anaconda_os_installer_discriminator: '{{ ansible_system }}' 3 | -------------------------------------------------------------------------------- /vars/Darwin.yml: -------------------------------------------------------------------------------- 1 | --- 2 | anaconda_os_installer_discriminator: '{{ ansible_distribution }}' 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **~*.retry 2 | Dockerfile.* 3 | requirements.yml 4 | !meta/requirements.yml 5 | **/*undo-tree* -------------------------------------------------------------------------------- /templates/anaconda.sh.j2: -------------------------------------------------------------------------------- 1 | export ANACONDA_DIR={{anaconda_link_dir}} 2 | export PATH=${ANACONDA_DIR}/bin:${PATH} 3 | -------------------------------------------------------------------------------- /vars/Archlinux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | anaconda_os_installer_discriminator: '{{ ansible_system }}' 3 | anaconda_dep_pkgs: 4 | - grep 5 | -------------------------------------------------------------------------------- /meta/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: andrewrothstein.bash 3 | version: v1.2.2 4 | - name: andrewrothstein.unarchivedeps 5 | version: 3.0.3 6 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | jobs: 3 | bake-ansible-images-v1: 4 | uses: andrewrothstein/.github/.github/workflows/bake-ansible-images-v1.yml@develop 5 | 'on': push 6 | -------------------------------------------------------------------------------- /test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Testing andrewrothstein.anaconda 3 | hosts: all 4 | vars: 5 | anaconda_make_sys_default: true 6 | anaconda_pkg_update: false 7 | roles: 8 | - role: '{{ playbook_dir }}' 9 | -------------------------------------------------------------------------------- /vars/Windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | anaconda_os_installer_discriminator: Windows 3 | anaconda_platform: '{{ anaconda_os_installer_discriminator }}-x86_64' 4 | anaconda_installer_sh: '{{ anaconda_name }}.exe' 5 | anaconda_checksum: "{{ anaconda_checksums[anaconda_installer_sh] | regex_replace('^md5:', '') }}" 6 | 7 | anaconda_install_dir: '{{ anaconda_parent_dir }}\Anaconda{{ anaconda_python_ver }}' 8 | 9 | anaconda_conda_bin: '{{ anaconda_install_dir }}\Scripts\conda.exe' 10 | -------------------------------------------------------------------------------- /platform-matrix-v1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "OS": "archlinux", 4 | "OS_VER": "latest" 5 | }, 6 | { 7 | "OS": "debian", 8 | "OS_VER": "bookworm" 9 | }, 10 | { 11 | "OS": "debian", 12 | "OS_VER": "bullseye" 13 | }, 14 | { 15 | "OS": "fedora", 16 | "OS_VER": "39" 17 | }, 18 | { 19 | "OS": "fedora", 20 | "OS_VER": "40" 21 | }, 22 | { 23 | "OS": "rockylinux", 24 | "OS_VER": "8" 25 | }, 26 | { 27 | "OS": "rockylinux", 28 | "OS_VER": "9" 29 | }, 30 | { 31 | "OS": "ubuntu", 32 | "OS_VER": "jammy" 33 | }, 34 | { 35 | "OS": "ubuntu", 36 | "OS_VER": "noble" 37 | } 38 | ] -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Andrew Rothstein 4 | company: BlackRock 5 | description: installs Anaconda 6 | galaxy_tags: 7 | - python 8 | - conda 9 | - anaconda 10 | license: MIT 11 | min_ansible_version: '2.0' 12 | namespace: andrewrothstein 13 | platforms: 14 | - name: ArchLinux 15 | versions: 16 | - all 17 | - name: Debian 18 | versions: 19 | - bookworm 20 | - bullseye 21 | - name: EL 22 | versions: 23 | - '8' 24 | - '9' 25 | - name: Fedora 26 | versions: 27 | - '39' 28 | - '40' 29 | - name: Ubuntu 30 | versions: 31 | - jammy 32 | - noble 33 | role_name: anaconda 34 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | anaconda_platform: '{{ anaconda_os_installer_discriminator }}-{{ ansible_machine }}' 3 | anaconda_name: 'Anaconda{{ anaconda_python_ver }}-{{ anaconda_ver }}-{{ anaconda_platform }}' 4 | anaconda_installer_sh: '{{ anaconda_name }}.sh' 5 | anaconda_installer_tmp_sh: '{{ anaconda_tmp_dir }}/{{ anaconda_installer_sh }}' 6 | anaconda_installer_url: '{{ anaconda_mirror }}/{{ anaconda_installer_sh }}' 7 | anaconda_checksum: '{{ anaconda_checksums[anaconda_installer_sh] }}' 8 | 9 | anaconda_install_dir: '{{ anaconda_parent_dir }}/{{ anaconda_name }}' 10 | anaconda_install_exe: '{{ anaconda_install_dir }}/bin/conda' 11 | 12 | anaconda_link_dir: '{{ anaconda_parent_dir }}/{{ anaconda_link_subdir }}' 13 | anaconda_conda_bin: '{{ anaconda_link_dir }}/bin/conda' 14 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Installing andrewrothstein.bash 3 | ansible.builtin.include_role: 4 | name: andrewrothstein.bash 5 | - name: Installing andrewrothstein.unarchivedeps 6 | ansible.builtin.include_role: 7 | name: andrewrothstein.unarchivedeps 8 | 9 | - name: Resolve platform specific vars 10 | ansible.builtin.include_vars: '{{ item }}' 11 | with_first_found: 12 | - files: 13 | - '{{ ansible_os_family }}.yml' 14 | - 'default.yml' 15 | paths: 16 | - '{{ role_path }}/vars' 17 | 18 | - name: Resolve platform specific tasks 19 | ansible.builtin.include_tasks: '{{ item }}' 20 | with_first_found: 21 | - files: 22 | - '{{ ansible_os_family }}.yml' 23 | - 'default.yml' 24 | paths: 25 | - '{{ role_path }}/tasks' 26 | -------------------------------------------------------------------------------- /dl-checksum.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -e 3 | DIR=~/Downloads 4 | MIRROR=https://repo.anaconda.com/archive 5 | 6 | dl() 7 | { 8 | local ver=$1 9 | local python_ver=$2 10 | local os=$3 11 | local arch=$4 12 | local dotexe=${5:-sh} 13 | 14 | local platform="${os}-${arch}" 15 | local file="Anaconda${python_ver}-${ver}-${platform}.${dotexe}" 16 | local url=$MIRROR/$file 17 | local lfile=$DIR/$file 18 | 19 | if [ ! -e $lfile ]; 20 | then 21 | curl -sSLf -o $lfile $url 22 | fi 23 | 24 | printf " # %s\n" $url 25 | printf " %s: sha256:%s\n" $file $(sha256sum $lfile | awk '{print $1}') 26 | } 27 | 28 | dlver () { 29 | local ver=$1 30 | local python_ver=$2 31 | dl $ver $python_ver Linux aarch64 32 | dl $ver $python_ver Linux s390x 33 | dl $ver $python_ver Linux x86_64 34 | dl $ver $python_ver MacOSX arm64 35 | dl $ver $python_ver MacOSX x86_64 36 | dl $ver $python_ver Windows x86_64 exe 37 | } 38 | 39 | dlver 2024.06-1 3 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrew Rothstein 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | andrewrothstein.anaconda 2 | ========= 3 | ![Build Status](https://github.com/andrewrothstein/ansible-anaconda/actions/workflows/build.yml/badge.svg) 4 | 5 | [![Join the chat at https://gitter.im/andrewrothstein/ansible-anaconda](https://badges.gitter.im/andrewrothstein/ansible-anaconda.svg)](https://gitter.im/andrewrothstein/ansible-anaconda?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | A role that installs [Anaconda](https://www.continuum.io/anaconda-overview). Please consider [andrewrothstein.conda-env](https://github.com/andrewrothstein/ansible-conda-env) for managing your Conda environments declaratively with Ansible too! 8 | 9 | Requirements 10 | ------------ 11 | 12 | See [meta/main.yml](meta/main.yml) 13 | 14 | Role Variables 15 | -------------- 16 | 17 | See [defaults/main.yml](defaults/main.yml) 18 | 19 | Dependencies 20 | ------------ 21 | 22 | See [meta/main.yml](meta/main.yml) 23 | 24 | Example Playbook 25 | ---------------- 26 | 27 | ```yml 28 | - hosts: servers 29 | roles: 30 | - andrewrothstein.anaconda 31 | ``` 32 | 33 | License 34 | ------- 35 | 36 | MIT 37 | 38 | Author Information 39 | ------------------ 40 | 41 | Andrew Rothstein 42 | -------------------------------------------------------------------------------- /library/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, UrbanSim Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /tasks/Windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check for existance of Anaconda 3 | ansible.windows.win_stat: 4 | path: '{{ anaconda_conda_bin }}' 5 | changed_when: false 6 | register: anaconda_conda_bin_ 7 | 8 | - name: Downloading and installing anaconda 9 | when: not anaconda_conda_bin_.stat.exists 10 | vars: 11 | anaconda_installer_dest: '{{ ansible_env.TEMP }}\{{ anaconda_installer_sh }}' 12 | block: 13 | - name: Download installer... 14 | ansible.windows.win_get_url: 15 | url: '{{ anaconda_installer_url }}' 16 | dest: '{{ anaconda_installer_dest }}' 17 | timeout: '{{ anaconda_timeout_seconds }}' 18 | register: anaconda_installer 19 | 20 | - name: Get installer information 21 | ansible.windows.win_stat: 22 | path: '{{ anaconda_installer.dest }}' 23 | checksum_algorithm: md5 24 | get_checksum: true 25 | register: anaconda_installer_ 26 | 27 | - name: Verify installer checksum 28 | vars: 29 | checksum: '{{ anaconda_installer_.stat.checksum }}' 30 | ansible.builtin.assert: 31 | that: 32 | - 'checksum == anaconda_checksum' 33 | msg: 'anaconda installer checksum mismatch' 34 | 35 | - name: Install... 36 | ansible.windows.win_package: 37 | path: '{{ anaconda_installer.dest }}' 38 | creates_path: '{{ anaconda_install_dir }}' 39 | state: present 40 | arguments: 41 | - /InstallationType={{ win_anaconda_installation_type }} 42 | - /AddToPath={{ win_anaconda_add_to_path | int }} 43 | - /RegisterPython={{ anaconda_make_sys_default | int }} 44 | - /S 45 | - /D={{ anaconda_install_dir }} 46 | 47 | always: 48 | - name: Delete installer... 49 | ansible.windows.win_file: 50 | path: '{{ anaconda_installer_dest }}' 51 | state: absent 52 | -------------------------------------------------------------------------------- /tasks/default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Installing OS pkg dependencies 3 | become: true 4 | become_user: root 5 | ansible.builtin.package: 6 | state: present 7 | name: '{{ anaconda_dep_pkgs | default([]) }}' 8 | 9 | - name: Check for installation at {{ anaconda_install_exe }} 10 | become: true 11 | ansible.builtin.stat: 12 | path: '{{ anaconda_install_exe }}' 13 | changed_when: false 14 | register: anaconda_conda_binary 15 | 16 | - name: Downloading and installing anaconda 17 | when: not anaconda_conda_binary.stat.exists 18 | block: 19 | - name: Ensure that {{ anaconda_tmp_dir }} directory exists 20 | ansible.builtin.file: 21 | path: "{{ anaconda_tmp_dir }}" 22 | state: directory 23 | mode: '755' 24 | 25 | - name: Downloading {{ anaconda_installer_url }} to {{ anaconda_installer_tmp_sh }} 26 | become: true 27 | become_user: root 28 | ansible.builtin.get_url: 29 | url: '{{ anaconda_installer_url }}' 30 | dest: '{{ anaconda_installer_tmp_sh }}' 31 | timeout: '{{ anaconda_timeout_seconds }}' 32 | checksum: '{{ anaconda_checksum }}' 33 | mode: '755' 34 | 35 | - name: Launching installer {{ anaconda_installer_tmp_sh }} with bash 36 | become: true 37 | become_user: root 38 | ansible.builtin.shell: |- 39 | [ -n "{{ anaconda_umask }}" ] && umask {{ anaconda_umask }}; 40 | TMPDIR={{ anaconda_tmp_dir }} \ 41 | bash "{{ anaconda_installer_tmp_sh }}" \ 42 | -b \ 43 | -p "{{ anaconda_install_dir }}"; 44 | args: 45 | creates: '{{ anaconda_install_dir }}' 46 | 47 | always: 48 | - name: Rm {{ anaconda_installer_tmp_sh }} 49 | become: true 50 | become_user: root 51 | ansible.builtin.file: 52 | path: '{{ anaconda_installer_tmp_sh }}' 53 | state: absent 54 | 55 | - name: Linking {{ anaconda_link_dir }} to {{ anaconda_install_dir }} 56 | become: true 57 | become_user: root 58 | ansible.builtin.file: 59 | src: '{{ anaconda_install_dir }}' 60 | dest: '{{ anaconda_link_dir }}' 61 | state: link 62 | 63 | - name: Updating all conda pkgs... 64 | become: true 65 | become_user: root 66 | when: anaconda_pkg_update 67 | ansible.builtin.shell: |- 68 | [ -n "{{ anaconda_umask }}" ] && umask {{ anaconda_umask }}; 69 | {{ anaconda_conda_bin }} update -y --all; 70 | changed_when: false 71 | 72 | - name: Remove conda-curl since it conflicts with the system curl 73 | become: true 74 | become_user: root 75 | conda: 76 | name: curl 77 | state: absent 78 | executable: '{{ anaconda_conda_bin }}' 79 | 80 | - name: Make system default python etc... 81 | become: true 82 | become_user: root 83 | when: anaconda_make_sys_default 84 | loop: 85 | - f: anaconda.sh 86 | d: /etc/profile.d 87 | loop_control: 88 | loop_var: tt 89 | ansible.builtin.template: 90 | src: '{{ tt.f }}.j2' 91 | dest: '{{ tt.d }}/{{ tt.f }}' 92 | mode: '{{ tt.m | default("644") }}' 93 | 94 | - name: Installing additional conda packages 95 | become: true 96 | become_user: root 97 | loop: '{{ anaconda_install_packages | default([]) }}' 98 | conda: 99 | name: '{{ item }}' 100 | state: present 101 | executable: '{{ anaconda_conda_bin }}' 102 | channels: '{{ anaconda_install_channels | default("") }}' 103 | -------------------------------------------------------------------------------- /library/conda.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | DOCUMENTATION = """ 5 | --- 6 | module: conda 7 | short_description: Manage Python libraries via conda 8 | description: 9 | > 10 | Manage Python libraries via conda. 11 | Can install, update, and remove packages. 12 | author: 13 | - Synthicity 14 | - Colin Nolan (@colin-nolan) 15 | notes: 16 | > 17 | Requires conda to already be installed. 18 | options: 19 | name: 20 | description: The name of a Python package to install. 21 | required: true 22 | version: 23 | description: The specific version of a package to install. 24 | required: false 25 | state: 26 | description: State in which to leave the Python package. "present" will install a package of the specified version 27 | if it is not installed (will not upgrade to latest if version is unspecified - will only install 28 | latest); "latest" will both install and subsequently upgrade a package to the latest version on each 29 | run; "absent" will uninstall the package if installed. 30 | required: false 31 | default: present 32 | choices: [ "present", "absent", "latest" ] 33 | channels: 34 | description: Extra channels to use when installing packages. 35 | required: false 36 | executable: 37 | description: Full path to the conda executable. 38 | required: false 39 | extra_args: 40 | description: Extra arguments passed to conda. 41 | required: false 42 | """ 43 | 44 | EXAMPLES = """ 45 | - name: install numpy via conda 46 | conda: 47 | name: numpy 48 | state: latest 49 | 50 | - name: install scipy 0.14 via conda 51 | conda: 52 | name: scipy 53 | version: "0.14" 54 | 55 | - name: remove matplotlib from conda 56 | conda: 57 | name: matplotlib 58 | state: absent 59 | """ 60 | 61 | RETURN = """ 62 | output: 63 | description: JSON output from Conda 64 | returned: `changed == True` 65 | type: dict 66 | stderr: 67 | description: stderr content written by Conda 68 | returned: `changed == True` 69 | type: str 70 | """ 71 | 72 | 73 | from shutil import which 74 | import os.path 75 | import json 76 | from ansible.module_utils.basic import AnsibleModule 77 | 78 | 79 | def run_package_operation(conda, name, version, state, dry_run, command_runner, on_failure, on_success): 80 | """ 81 | Runs Conda package operation. 82 | 83 | This method is intentionally decoupled from `AnsibleModule` to allow it to be easily tested in isolation. 84 | :param conda: location of the Conda executable 85 | :param name: name of the package of interest 86 | :param version: version of the package (`None` for latest) 87 | :param state: state the package should be in 88 | :param dry_run: will "pretend" to make changes only if `True` 89 | :param command_runner: method that executes a given Conda command (given as list of string arguments), which returns 90 | JSON and returns a tuple where the first argument is the outputted JSON and the second is anything written to stderr 91 | :param on_failure: method that takes any kwargs to be called on failure 92 | :param on_success: method that takes any kwargs to be called on success 93 | """ 94 | correct_version_installed = check_package_installed(command_runner, conda, name, version) 95 | 96 | # TODO: State should be an "enum" (or whatever the Py2.7 equivalent is) 97 | if not correct_version_installed and state != 'absent': 98 | try: 99 | output, stderr = install_package(command_runner, conda, name, version, dry_run=dry_run) 100 | on_success(changed=True, output=output, stderr=stderr) 101 | except CondaPackageNotFoundError: 102 | on_failure(msg='Conda package "%s" not found' % (get_install_target(name, version, ))) 103 | 104 | elif state == 'absent': 105 | try: 106 | output, stderr = uninstall_package(command_runner, conda, name, dry_run=dry_run) 107 | on_success(changed=True, output=output, stderr=stderr) 108 | except CondaPackageNotFoundError: 109 | on_success(changed=False) 110 | 111 | else: 112 | on_success(changed=False) 113 | 114 | 115 | def check_package_installed(command_runner, conda, name, version): 116 | """ 117 | Check whether a package with the given name and version is installed. 118 | :param command_runner: method that executes a given Conda command (given as list of string arguments), which returns 119 | JSON and returns a tuple where the first argument is the outputted JSON and the second is anything written to stderr 120 | :param name: the name of the package to check if installed 121 | :param version: the version of the package to check if installed (`None` if check for latest) 122 | :return: `True` if a package with the given name and version is installed 123 | :raises CondaUnexpectedOutputError: if the JSON returned by Conda was unexpected 124 | """ 125 | output, stderr = run_conda_package_command( 126 | command_runner, name, version, [conda, 'install', '--json', '--dry-run', get_install_target(name, version)]) 127 | 128 | if 'message' in output and output['message'] == 'All requested packages already installed.': 129 | return True 130 | elif 'actions' in output and len(output['actions']) > 0: 131 | return False 132 | else: 133 | raise CondaUnexpectedOutputError(output, stderr) 134 | 135 | 136 | def install_package(command_runner, conda, name, version=None, dry_run=False): 137 | """ 138 | Install a package with the given name and version. Version will default to latest if `None`. 139 | """ 140 | command = [conda, 'install', '--yes', '--json', get_install_target(name, version)] 141 | if dry_run: 142 | command.insert(-1, '--dry-run') 143 | 144 | return run_conda_package_command(command_runner, name, version, command) 145 | 146 | 147 | def uninstall_package(command_runner, conda, name, dry_run=False): 148 | """ 149 | Use Conda to remove a package with the given name. 150 | """ 151 | command = [conda, 'remove', '--yes', '--json', name] 152 | if dry_run: 153 | command.insert(-1, '--dry-run') 154 | 155 | return run_conda_package_command(command_runner, name, None, command) 156 | 157 | 158 | def find_conda(executable): 159 | """ 160 | If `executable` is not None, checks whether it points to a valid file 161 | and returns it if this is the case. Otherwise tries to find the `conda` 162 | executable in the path. Calls `fail_json` if either of these fail. 163 | """ 164 | if not executable: 165 | conda = which('conda') 166 | if conda: 167 | return conda 168 | else: 169 | if os.path.isfile(executable): 170 | return executable 171 | 172 | raise CondaExecutableNotFoundError() 173 | 174 | 175 | def add_channels_to_command(command, channels): 176 | """ 177 | Add extra channels to a conda command by splitting the channels 178 | and putting "--channel" before each one. 179 | """ 180 | if channels: 181 | channels = channels.strip().split() 182 | dashc = [] 183 | for channel in channels: 184 | dashc.append('--channel') 185 | dashc.append(channel) 186 | 187 | return command[:2] + dashc + command[2:] 188 | else: 189 | return command 190 | 191 | 192 | def add_extras_to_command(command, extras): 193 | """ 194 | Add extra arguments to a conda command by splitting the arguments 195 | on white space and inserting them after the second item in the command. 196 | """ 197 | if extras: 198 | extras = extras.strip().split() 199 | return command[:2] + extras + command[2:] 200 | else: 201 | return command 202 | 203 | 204 | def parse_conda_stdout(stdout): 205 | """ 206 | Parses the given output from Conda. 207 | :param stdout: the output from stdout 208 | :return: standard out as parsed JSON else `None` if non-JSON format 209 | """ 210 | # Conda spews loading progress reports onto stdout(!?), which need ignoring. Bug observed in Conda version 4.3.25. 211 | split_lines = stdout.strip().split("\n") 212 | while len(split_lines) > 0: 213 | line = split_lines.pop(0).strip('\x00') 214 | try: 215 | line_content = json.loads(line) 216 | if "progress" not in line_content and "maxval" not in line_content: 217 | # Looks like this was the output, not a progress update 218 | return line_content 219 | except ValueError: 220 | split_lines.insert(0, line) 221 | break 222 | 223 | try: 224 | return json.loads("".join(split_lines)) 225 | except ValueError: 226 | return None 227 | 228 | 229 | def run_conda_package_command(command_runner, name, version, command): 230 | """ 231 | Runs a Conda command related to a particular package. 232 | :param command_runner: runner of Conda commands 233 | :param name: the name of the package the command refers to 234 | :param version: the version of the package that the command is referring to 235 | :param command: the Conda command 236 | :raises CondaPackageNotFoundError: if the package referred to by this command is not found 237 | """ 238 | try: 239 | return command_runner(command) 240 | except CondaCommandJsonDescribedError as e: 241 | if 'exception_name' in e.output and e.output['exception_name'] in ('PackageNotFoundError', 'PackagesNotFoundError'): 242 | raise CondaPackageNotFoundError(name, version) 243 | else: 244 | raise 245 | 246 | 247 | def get_install_target(name, version): 248 | """ 249 | Gets install target string for a package with the given name and version. 250 | :param name: the package name 251 | :param version: the package version (`None` if latest) 252 | :return: the target string that Conda can refer to the given package as 253 | """ 254 | install_target = name 255 | if version is not None: 256 | install_target = '%s=%s' % (name, version) 257 | return install_target 258 | 259 | 260 | class CondaCommandError(Exception): 261 | """ 262 | Error raised when a Conda command fails. 263 | """ 264 | def __init__(self, command, stdout, stderr): 265 | self.command = command 266 | self.stdout = stdout 267 | self.stderr = stderr 268 | 269 | stdout = ' stdout: %s.' % self.stdout if self.stdout.strip() != '' else '' 270 | stderr = ' stderr: %s.' % self.stderr if self.stderr.strip() != '' else '' 271 | 272 | super(CondaCommandError, self).__init__( 273 | 'Error running command: %s.%s%s' % (self.command, stdout, stderr)) 274 | 275 | 276 | class CondaCommandJsonDescribedError(CondaCommandError): 277 | """ 278 | Error raised when a Conda command does not output JSON. 279 | """ 280 | def __init__(self, command, output, stderr): 281 | self.output = output 282 | super(CondaCommandJsonDescribedError, self).__init__(command, json.dumps(output), stderr) 283 | 284 | 285 | class CondaPackageNotFoundError(Exception): 286 | """ 287 | Error raised when a Conda package has not been found in the package repositories that were searched. 288 | """ 289 | def __int__(self, name, version): 290 | self.name = name 291 | self.version = version 292 | super(CondaPackageNotFoundError, self).__init__( 293 | 'Conda package "%s" not found' % (get_install_target(self.name, self.version), )) 294 | 295 | 296 | class CondaUnexpectedOutputError(Exception): 297 | """ 298 | Error raised when the running of a Conda command has resulted in an unexpected output. 299 | """ 300 | def __int__(self, output, stderr): 301 | self.output = output 302 | self.stderr = stderr 303 | 304 | stderr = 'stderr: %s' % self.stderr if self.stderr.strip() != '' else '' 305 | super(CondaUnexpectedOutputError, self).__init__( 306 | 'Unexpected output from Conda (may be due to a change in Conda\'s output format): "%output".%s' 307 | % (self.output, stderr)) 308 | 309 | 310 | class CondaExecutableNotFoundError(Exception): 311 | """ 312 | Error raised when the Conda executable was not found. 313 | """ 314 | def __init__(self): 315 | super(CondaExecutableNotFoundError, self).__init__('Conda executable not found.') 316 | 317 | 318 | def _run_conda_command(module, command): 319 | """ 320 | Runs the given Conda command. 321 | :param module: Ansible module 322 | :param command: the Conda command to run, which must return JSON 323 | """ 324 | command = add_channels_to_command(command, module.params['channels']) 325 | command = add_extras_to_command(command, module.params['extra_args']) 326 | 327 | rc, stdout, stderr = module.run_command(command) 328 | output = parse_conda_stdout(stdout) 329 | 330 | if output is None: 331 | raise CondaCommandError(command, stdout, stderr) 332 | if rc != 0: 333 | raise CondaCommandJsonDescribedError(command, output, stderr) 334 | 335 | return output, stderr 336 | 337 | 338 | def _main(): 339 | """ 340 | Entrypoint. 341 | """ 342 | module = AnsibleModule( 343 | argument_spec={ 344 | 'name': {'required': True, 'type': 'str'}, 345 | 'version': {'default': None, 'required': False, 'type': 'str'}, 346 | 'state': { 347 | 'default': 'present', 348 | 'required': False, 349 | 'choices': ['present', 'absent', 'latest'] 350 | }, 351 | 'channels': {'default': None, 'required': False}, 352 | 'executable': {'default': None, 'required': False}, 353 | 'extra_args': {'default': None, 'required': False, 'type': 'str'} 354 | }, 355 | supports_check_mode=True) 356 | 357 | conda = find_conda(module.params['executable']) 358 | name = module.params['name'] 359 | state = module.params['state'] 360 | version = module.params['version'] 361 | 362 | if state == 'latest' and version is not None: 363 | module.fail_json(msg='`version` must not be set if `state == "latest"` (`latest` upgrades to newest version)') 364 | 365 | def command_runner(command): 366 | return _run_conda_command(module, command) 367 | 368 | run_package_operation( 369 | conda, name, version, state, module.check_mode, command_runner, module.fail_json, module.exit_json) 370 | 371 | 372 | if __name__ == '__main__': 373 | _main() 374 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # main Anaconda download server 3 | anaconda_mirror: https://repo.continuum.io/archive 4 | 5 | # version of python (2|3) 6 | anaconda_python_ver: 3 7 | 8 | # anaconda version 9 | anaconda_ver: '2024.06-1' 10 | 11 | # when downloading the anaconda binary it might take a while 12 | # don't let you less great network connection cause the role to falter 13 | anaconda_timeout_seconds: 600 14 | 15 | # add the anaconda python onto the front of your path. 16 | # Caveat Emptor: if your OS package manager is python based careful about jamming it 17 | anaconda_make_sys_default: false 18 | 19 | anaconda_parent_dir: "{{ ansible_env.USERPROFILE + '\\AppData\\Local\\Continuum' if ansible_os_family == 'Windows' else '/usr/local' }}" 20 | anaconda_link_subdir: anaconda 21 | 22 | anaconda_pkg_update: true 23 | 24 | # install a a list of packages into the root conda env. please consider using conda envs effectively! 25 | # anaconda_install_packages: 26 | # - package1 27 | # - package2 28 | 29 | # control the install channels 30 | # anaconda_install_channels: "defaults conda-forge bioconda" 31 | 32 | # additional control over windows-installer specific options 33 | win_anaconda_installation_type: JustMe 34 | win_anaconda_add_to_path: true 35 | 36 | anaconda_tmp_dir: /tmp/anaconda-tmp 37 | 38 | # It might be necessary to change the umask on some systems, so that users 39 | # other than "root" can use anaconda. 40 | # 41 | # anaconda_umask: '022' 42 | anaconda_umask: '' 43 | 44 | # anaconda checksums... 45 | # https://repo.continuum.io/archive/ 46 | anaconda_checksums: 47 | Anaconda2-4.2.0-Linux-x86_64.sh: sha256:beee286d24fb37dd6555281bba39b3deb5804baec509a9dc5c69185098cf661a 48 | Anaconda3-4.2.0-Linux-x86_64.sh: sha256:73b51715a12b6382dd4df3dd1905b531bd6792d4aa7273b2377a0436d45f0e78 49 | Anaconda2-4.2.0-MacOSX-x86_64.sh: sha256:a8b3ef86233635d9dcc3499dc384980762a0b42d354a318f8307029c399db452 50 | Anaconda3-4.2.0-MacOSX-x86_64.sh: sha256:95448921601e1952e01a17ba9767cd3621c154af7fc52dd6b7f57d462155a358 51 | Anaconda2-4.2.0-Windows-x86_64.exe: md5:0a30d509568724dac0ae193e139b9c37 52 | Anaconda3-4.2.0-Windows-x86_64.exe: md5:0ca5ef4dcfe84376aad073bbb3f8db00 53 | Anaconda2-4.3.0-Linux-x86_64.sh: sha256:7c52e6e99aabb24a49880130615a48e685da444c3c14eb48d6a65f3313bf745c 54 | Anaconda3-4.3.0-Linux-x86_64.sh: sha256:e9169c3a5029aa820393ac92704eb9ee0701778a085ca7bdc3c57b388ac1beb6 55 | Anaconda2-4.3.0-MacOSX-x86_64.sh: sha256:834ac0287062929ab5930661735ee617fd379bdfe79f3e0a20aebd614835b6c5 56 | Anaconda3-4.3.0-MacOSX-x86_64.sh: sha256:c53059b810c5e7a9a5ef9c46a7ed76675dfc7183f4ea867b4d81449cbd5a093d 57 | Anaconda2-4.3.0-Windows-x86_64.exe: md5:2c02e21e542d61760c3e19bf0b3086fe 58 | Anaconda3-4.3.0-Windows-x86_64.exe: md5:137043b3f9860519967759fc8ea76514 59 | Anaconda2-4.3.0.1-Windows-x86_64.exe: md5:56b181af1959de40e67fb5ef50612ae2 60 | Anaconda3-4.3.0.1-Windows-x86_64.exe: md5:07ea8c5a2306ac8fabf3902bd6623787 61 | Anaconda2-4.3.1-Linux-x86_64.sh: sha256:e9b8f2645df6b1527ba56d61343162e0794acc3ee8dde2a6bba353719e2d878d 62 | Anaconda3-4.3.1-Linux-x86_64.sh: sha256:4447b93d2c779201e5fb50cfc45de0ec96c3804e7ad0fe201ab6b99f73e90302 63 | Anaconda2-4.3.1-MacOSX-x86_64.sh: sha256:35261360f2b01793f441b29715a94052dceaef1137866b7323c76be83c5bcc1a 64 | Anaconda3-4.3.1-MacOSX-x86_64.sh: sha256:a42267203e207cb5e0f539e0d879ead12e436311825c7114d0edd880d001b539 65 | Anaconda2-4.3.1-Windows-x86_64.exe: md5:bfd41f4de09a690f8b3525d3fb79bd2f 66 | Anaconda3-4.3.1-Windows-x86_64.exe: md5:16f337426454eac463fd0d41c6d2bbb8 67 | Anaconda2-4.4.0-Linux-x86_64.sh: sha256:2d30b91ed4d215b6b4a15162a3389e9057b15445a0c02da71bd7bd272e7b824e 68 | Anaconda3-4.4.0-Linux-x86_64.sh: sha256:3301b37e402f3ff3df216fe0458f1e6a4ccbb7e67b4d626eae9651de5ea3ab63 69 | Anaconda2-4.4.0-MacOSX-x86_64.sh: sha256:ab95aef1110c2a385fd39a17e5f11dfbaabce25c1a5944598de164d7a2772969 70 | Anaconda3-4.4.0-MacOSX-x86_64.sh: sha256:10fe58f09ae524df2548d17b8bb1e75db17da597a6ec10d695ce01387a2d742 71 | Anaconda2-4.4.0-Windows-x86_64.exe: md5:0f60aa52ef3a5d6170aeb6f7e3651f91 72 | Anaconda3-4.4.0-Windows-x86_64.exe: md5:aa200a1c059a551e0ba9a5314a9554a5 73 | Anaconda2-5.0.0-Linux-x86_64.sh: sha256:58a7117f89c40275114bf7e824a613a963da2b0fe63f2ec3c1175fea785b468e 74 | Anaconda3-5.0.0-Linux-x86_64.sh: sha256:67f5c20232a3e493ea3f19a8e273e0618ab678fa14b03b59b1783613062143e9 75 | Anaconda2-5.0.0-MacOSX-x86_64.sh: sha256:d85198c63657924fae11b6ea5961f50d81d09a1185d6f0a9a9d5bc69eb788ccc 76 | Anaconda3-5.0.0-MacOSX-x86_64.sh: sha256:23df1e3a38a6b4aaa0ab559d0c1e51be76eca5d75cb595d473d223c8d17e762d 77 | Anaconda2-5.0.0-Windows-x86_64.exe: md5:8323b1d5f0b1c3fdb5b85efbb099beb0 78 | Anaconda3-5.0.0-Windows-x86_64.exe: md5:fee3fad608d0006afa5c7bca4de3d02b 79 | Anaconda2-5.0.1-Linux-x86_64.sh: md5:dc13fe5502cd78dd03e8a727bb9be63f 80 | Anaconda3-5.0.1-Linux-x86_64.sh: md5:c989ecc8b648ab8a64731aaee9ed2e7e 81 | Anaconda2-5.0.1-MacOSX-x86_64.sh: md5:17314016dced36614a3bef8ff3db7066 82 | Anaconda3-5.0.1-MacOSX-x86_64.sh: md5:3c0f4bf6d9a68d91f6da65051046e106 83 | Anaconda2-5.0.1-Windows-x86_64.exe: md5:b8d9bc02edd61af3f7ece3d07e726e91 84 | Anaconda3-5.0.1-Windows-x86_64.exe: md5:3dde7dbbef158db6dc44fce495671c92 85 | Anaconda2-5.1.0-Linux-x86_64.sh: md5:5b1b5784cae93cf696e11e66983d8756 86 | Anaconda3-5.1.0-Linux-x86_64.sh: md5:966406059cf7ed89cc82eb475ba506e5 87 | Anaconda2-5.1.0-MacOSX-x86_64.sh: md5:e9845ccf67542523c5be09552311666e 88 | Anaconda3-5.1.0-MacOSX-x86_64.sh: md5:047e12523fd287149ecd80c803598429 89 | Anaconda2-5.1.0-Windows-x86_64.exe: md5:b16d6d6858fc7decf671ac71e6d7cfdb 90 | Anaconda3-5.1.0-Windows-x86_64.exe: md5:83a8b1edcb21fa0ac481b23f65b604c6 91 | Anaconda2-5.2.0-Windows-x86_64.exe: md5:595e427e4b625b6eab92623a28dc4e21 92 | Anaconda3-5.2.0-Windows-x86_64.exe: md5:62244c0382b8142743622fdc3526eda7 93 | Anaconda2-2018.12-Linux-ppc64le.sh: md5:d50ce6eb037f72edfe8f94f90d61aca6 94 | Anaconda2-2018.12-Linux-x86.sh: md5:7d26c7551af6802eb83ecd34282056d7 95 | Anaconda2-2018.12-Linux-x86_64.sh: md5:84f39388da2c747477cf14cb02721b93 96 | Anaconda2-2018.12-MacOSX-x86_64.sh: md5:f4d8b10e9a754884fb96e68e0e0b276a 97 | Anaconda2-2018.12-Windows-x86.exe: md5:f123fda0ec8928bb7d55d1ca72c0d784 98 | Anaconda2-2018.12-Windows-x86_64.exe: md5:10ff4176a94fcff86e6253b0cc82c782 99 | Anaconda3-2018.12-Linux-ppc64le.sh: md5:a775fb6d6c441b899ff2327bd9dadc6d 100 | Anaconda3-2018.12-Linux-x86.sh: md5:4c9922d1547128b866c6b9cf750c03c7 101 | Anaconda3-2018.12-Linux-x86_64.sh: md5:c9af603d89656bc89680889ef1f92623 102 | Anaconda3-2018.12-MacOSX-x86_64.sh: md5:910c8f411f16b02813b3a2cd95462a81 103 | Anaconda3-2018.12-Windows-x86.exe: md5:dc26da1eea1e5cc78121b1d3f80a6e9c 104 | Anaconda3-2018.12-Windows-x86_64.exe: md5:8d068f924a77e8d015906e81e91b31ab 105 | Anaconda2-2019.03-Linux-ppc64le.sh: md5:ec65edf84f63c64a876aabc704a090b97 106 | Anaconda2-2019.03-Linux-x86_64.sh: md5:dd87c316e211891df8889c52d9167a5d 107 | Anaconda2-2019.03-MacOSX-x86_64.sh: md5:fc7f811d92e39c17c20fac1f43200043 108 | Anaconda2-2019.03-Windows-x86.exe: md5:4b055a00f4f99352bd29db7a4f691f6e 109 | Anaconda2-2019.03-Windows-x86_64.exe: md5:042809940fb2f60d979eac02fc4e6c82 110 | Anaconda3-2019.03-Linux-ppc64le.sh: md5:510c8d6f10f2ffad0b185adbbdddf7f9 111 | Anaconda3-2019.03-Linux-x86_64.sh: md5:43caea3d726779843f130a7fb2d380a2 112 | Anaconda3-2019.03-MacOSX-x86_64.sh: md5:46709a416be6934a7fd5d02b021d2687 113 | Anaconda3-2019.03-Windows-x86.exe: md5:f1f636e5d34d129b6b996ff54f4a05b1 114 | Anaconda3-2019.03-Windows-x86_64.exe: md5:bfb4da8555ef5b1baa064ef3f0c7b582 115 | Anaconda2-2019.10-Linux-ppc64le.sh: md5:6b9809bf5d36782bfa1e35b791d983a0 116 | Anaconda2-2019.10-Linux-x86_64.sh: md5:69c64167b8cf3a8fc6b50d12d8476337 117 | Anaconda2-2019.10-MacOSX-x86_64.sh: md5:311aeb49cbe6d296f499efcd01a73f5e 118 | Anaconda2-2019.10-Windows-x86.exe: md5:0057a4b9d432ef0b78badee4f74a54a0 119 | Anaconda2-2019.10-Windows-x86_64.exe: md5:b152e6f36032ed414ad88cca9ace331a 120 | Anaconda3-2019.10-Linux-ppc64le.sh: md5:9dd413b0f2d0c68f387541428fe8d565 121 | Anaconda3-2019.10-Linux-x86_64.sh: md5:b77a71c3712b45c8f33c7b2ecade366c 122 | Anaconda3-2019.10-MacOSX-x86_64.sh: md5:1a56194e89795b7ebbfe405b09d9c42d 123 | Anaconda3-2019.10-Windows-x86.exe: md5:0e71632df6a17f625c1103b34f66e8ba 124 | Anaconda3-2019.10-Windows-x86_64.exe: md5:fafcdbf5feb6dc3081bf07cbb8af1dbe 125 | # https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-ppc64le.sh 126 | Anaconda3-2020.02-Linux-ppc64le.sh: sha256:d6d1827a38b988cbbe714d6e0357c9e251c84641a0c70cda51861ed9abb38804 127 | # https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh 128 | Anaconda3-2020.02-Linux-x86_64.sh: sha256:2b9f088b2022edb474915d9f69a803d6449d5fdb4c303041f60ac4aefcc208bb 129 | # https://repo.anaconda.com/archive/Anaconda3-2020.02-MacOSX-x86_64.sh 130 | Anaconda3-2020.02-MacOSX-x86_64.sh: sha256:d237e6c976eb9c58368ca156a51bd913d63a3b5fea32689342733c99d14b6f2e 131 | # https://repo.anaconda.com/archive/Anaconda3-2020.02-Windows-x86_64.exe 132 | Anaconda3-2020.02-Windows-x86_64.exe: sha256:83c2f53c7174253adcc2de7d1293a7408c37b295abbbb8feca32cb8428a26158 133 | # https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-ppc64le.sh 134 | Anaconda3-2020.07-Linux-ppc64le.sh: sha256:0df7c3784973ab46a9ef9848aced01311d08a71d79a18d5ed79dccdae8c8dea7 135 | # https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-x86_64.sh 136 | Anaconda3-2020.07-Linux-x86_64.sh: sha256:38ce717758b95b3bd0b1797cc6ccfb76f29a90c25bdfa50ee45f11e583edfdbf 137 | # https://repo.anaconda.com/archive/Anaconda3-2020.07-MacOSX-x86_64.sh 138 | Anaconda3-2020.07-MacOSX-x86_64.sh: sha256:3980c2a57fde5de2ccfdf0d7973f95ac1a3fa63351642e6735c50fc3791ef0f1 139 | # https://repo.anaconda.com/archive/Anaconda3-2020.07-Windows-x86_64.exe 140 | Anaconda3-2020.07-Windows-x86_64.exe: sha256:66acb9bdf7d2d5925df8762311a85ad72f57dfd340447bf00636d35a28454244 141 | # https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-ppc64le.sh 142 | Anaconda3-2020.11-Linux-ppc64le.sh: sha256:870535ada0a8ae75eeda8cd2bf7dde853ac9f4949b20e1b5641f1843a655f3b8 143 | # https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh 144 | Anaconda3-2020.11-Linux-x86_64.sh: sha256:cf2ff493f11eaad5d09ce2b4feaa5ea90db5174303d5b3fe030e16d29aeef7de 145 | # https://repo.anaconda.com/archive/Anaconda3-2020.11-MacOSX-x86_64.sh 146 | Anaconda3-2020.11-MacOSX-x86_64.sh: sha256:ec11e325c792a6f49dbdbe5e641991d0a29788689176d7e54da97def9532c762 147 | # https://repo.anaconda.com/archive/Anaconda3-2020.11-Windows-x86_64.exe 148 | Anaconda3-2020.11-Windows-x86_64.exe: sha256:aa523115daf31c431bb392faf75e70d35ada935e36dc7b1dd8902baee240bcc1 149 | # https://repo.anaconda.com/archive/Anaconda3-2021.05-Linux-ppc64le.sh 150 | Anaconda3-2021.05-Linux-ppc64le.sh: sha256:097064807a9adae3f91fc4c5852cd90df2b77fc96505929bb25bf558f1eef76f 151 | # https://repo.anaconda.com/archive/Anaconda3-2021.05-Linux-x86_64.sh 152 | Anaconda3-2021.05-Linux-x86_64.sh: sha256:2751ab3d678ff0277ae80f9e8a74f218cfc70fe9a9cdc7bb1c137d7e47e33d53 153 | # https://repo.anaconda.com/archive/Anaconda3-2021.05-MacOSX-x86_64.sh 154 | Anaconda3-2021.05-MacOSX-x86_64.sh: sha256:0407bee87eeecad521f1e38eb607b0a85babef4c1b47516dc5c090e152eba5d5 155 | # https://repo.anaconda.com/archive/Anaconda3-2021.05-Windows-x86_64.exe 156 | Anaconda3-2021.05-Windows-x86_64.exe: sha256:93db42390444019e98b442ab281e1091671b6dce64daf08928d337ffc83cf3d2 157 | # https://repo.anaconda.com/archive/Anaconda3-2021.11-Linux-ppc64le.sh 158 | Anaconda3-2021.11-Linux-ppc64le.sh: sha256:7eb6a95925ee756240818599f8dcbba7a155adfb05ef6cd5336aa3c083de65f3 159 | # https://repo.anaconda.com/archive/Anaconda3-2021.11-Linux-x86_64.sh 160 | Anaconda3-2021.11-Linux-x86_64.sh: sha256:fedf9e340039557f7b5e8a8a86affa9d299f5e9820144bd7b92ae9f7ee08ac60 161 | # https://repo.anaconda.com/archive/Anaconda3-2021.11-MacOSX-x86_64.sh 162 | Anaconda3-2021.11-MacOSX-x86_64.sh: sha256:6a9217d1a08c599f860045d56ef64fc6c3e3112b55cc97f3d07c573d7bbcdb58 163 | # https://repo.anaconda.com/archive/Anaconda3-2021.11-Windows-x86_64.exe 164 | Anaconda3-2021.11-Windows-x86_64.exe: sha256:1b3d593d1deb22b835be5c68897075e0fc9dea240ab4191c55674aba259a78ff 165 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-aarch64.sh 166 | Anaconda3-2022.05-Linux-aarch64.sh: sha256:dc6bb4eab3996e0658f8bc4bbd229c18f55269badd74acc36d9e23143268b795 167 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-ppc64le.sh 168 | Anaconda3-2022.05-Linux-ppc64le.sh: sha256:a50bf5bd26b5c5a2c24028c1aff6da2fa4d4586ca43ae3acdf7ffb9b50d7f282 169 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-s390x.sh 170 | Anaconda3-2022.05-Linux-s390x.sh: sha256:c14415df69e439acd7458737a84a45c6067376cbec2fccf5e2393f9837760ea7 171 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh 172 | Anaconda3-2022.05-Linux-x86_64.sh: sha256:a7c0afe862f6ea19a596801fc138bde0463abcbce1b753e8d5c474b506a2db2d 173 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-MacOSX-arm64.sh 174 | Anaconda3-2022.05-MacOSX-arm64.sh: sha256:a12119931945a9a1453993582259cc67318a9a75a15731e5ccc15365e7f88a36 175 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-MacOSX-x86_64.sh 176 | Anaconda3-2022.05-MacOSX-x86_64.sh: sha256:1a10c06660ebe1204e538b4e9d810142441af9dfd74b077eee2761ec6e675f39 177 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-Windows-x86.exe 178 | Anaconda3-2022.05-Windows-x86.exe: sha256:cd8c688349bcd1f429e3b383620fb0d19f52be0f765b2eae78d63b41aefb2e73 179 | # https://repo.anaconda.com/archive/Anaconda3-2022.05-Windows-x86_64.exe 180 | Anaconda3-2022.05-Windows-x86_64.exe: sha256:2766eb102f9d65da36d262b651777358de39fbe5f1a74f9854a2e5e29caeeeec 181 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-aarch64.sh 182 | Anaconda3-2022.10-Linux-aarch64.sh: sha256:fbadbfae5992a8c96af0a4621262080eea44e22baee2172e3dfb640f5cf8d22d 183 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-ppc64le.sh 184 | Anaconda3-2022.10-Linux-ppc64le.sh: sha256:8fdebc79f63b74daad421a2674d43299fa9c5007d85cf00e8dc1a81fbf2787e4 185 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-s390x.sh 186 | Anaconda3-2022.10-Linux-s390x.sh: sha256:f5ccc24aedab1f3f9cccf1945ca1061bee194fa42a212ec26425f3b77fdd943a 187 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-x86_64.sh 188 | Anaconda3-2022.10-Linux-x86_64.sh: sha256:e7ecbccbc197ebd7e1f211c59df2e37bc6959d081f2235d387e08c9026666acd 189 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-MacOSX-arm64.sh 190 | Anaconda3-2022.10-MacOSX-arm64.sh: sha256:200700077db8eed762fbc996b830c3f8cc5a2bb7d6b20bb367147eb35f2dcc72 191 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-MacOSX-x86_64.sh 192 | Anaconda3-2022.10-MacOSX-x86_64.sh: sha256:dfcd1431a8206506799cb142b04d2db3be8a28671e5c3672920c09c71246dde0 193 | # https://repo.anaconda.com/archive/Anaconda3-2022.10-Windows-x86_64.exe 194 | Anaconda3-2022.10-Windows-x86_64.exe: sha256:38b9d53a579843fe41fd05fd3c4f9ac3887f580e7bd9b43f220bbc3aea2367eb 195 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-Linux-aarch64.sh 196 | Anaconda3-2023.07-1-Linux-aarch64.sh: sha256:2ebe549375f3f5ffec9558a8a8405ebd697e69c8133b8f9c1c5cd4ff69d1cc74 197 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-Linux-ppc64le.sh 198 | Anaconda3-2023.07-1-Linux-ppc64le.sh: sha256:ee149f55ebdd3f15fc1db4e9cddb5126da62e7a193fa15026c9fa009a2575d0a 199 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-Linux-s390x.sh 200 | Anaconda3-2023.07-1-Linux-s390x.sh: sha256:49aad1bc077334f30177443c234f3c982f1c9751fc78c4c29fb4cf736e4f61ef 201 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-Linux-x86_64.sh 202 | Anaconda3-2023.07-1-Linux-x86_64.sh: sha256:111ce0a7f26e606863008a9519fd608b1493e483b6f487aea71d82b13fe0967e 203 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-MacOSX-arm64.sh 204 | Anaconda3-2023.07-1-MacOSX-arm64.sh: sha256:322045ad100dcc380decde5812db58c617901c6a8ac46dd7818080fe3ae19f8e 205 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-MacOSX-x86_64.sh 206 | Anaconda3-2023.07-1-MacOSX-x86_64.sh: sha256:803b2d0c5a142af3de14b410517c2c8889eaceb1b784d4c121512ebda13af6f8 207 | # https://repo.anaconda.com/archive/Anaconda3-2023.07-1-Windows-x86_64.exe 208 | Anaconda3-2023.07-1-Windows-x86_64.exe: sha256:f52d9d658e49d62754266e4e38e0dfc46fabda485de7139cef263187472f7445 209 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-aarch64.sh 210 | Anaconda3-2023.09-0-Linux-aarch64.sh: sha256:69ee26361c1ec974199bce5c0369e3e9a71541de7979d2b9cfa4af556d1ae0ea 211 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-ppc64le.sh 212 | Anaconda3-2023.09-0-Linux-ppc64le.sh: sha256:5ea1ed9808af95eb2655fe6a4ffdb66bea66ecd1d053fc2ee69eacc7685ef665 213 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-s390x.sh 214 | Anaconda3-2023.09-0-Linux-s390x.sh: sha256:ee817071a2ad94e044fb48061a721bc86606b2f4906b705e4f42177eeb3ca7c5 215 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh 216 | Anaconda3-2023.09-0-Linux-x86_64.sh: sha256:6c8a4abb36fbb711dc055b7049a23bbfd61d356de9468b41c5140f8a11abd851 217 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-MacOSX-arm64.sh 218 | Anaconda3-2023.09-0-MacOSX-arm64.sh: sha256:34121775d9e30a6ea12af0a462e1881670b0c175b426e06fd7b1581625ebd69b 219 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-MacOSX-x86_64.sh 220 | Anaconda3-2023.09-0-MacOSX-x86_64.sh: sha256:0c64a2c634fe31335079d97340c277c81b3f0c9dfe862a06599570640ac897a4 221 | # https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Windows-x86_64.exe 222 | Anaconda3-2023.09-0-Windows-x86_64.exe: sha256:810da8bff79c10a708b7af9e8f21e6bb47467261a31741240f27bd807f155cb9 223 | # https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-aarch64.sh 224 | Anaconda3-2024.06-1-Linux-aarch64.sh: sha256:b4be0ad2052236882402902a31d32cd37635d3db194a42f977be0d68a8ff1a31 225 | # https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-s390x.sh 226 | Anaconda3-2024.06-1-Linux-s390x.sh: sha256:1b3f4ef4147137fb1861f8251679ea96e651a7c405993c61e39441e43ee2dd11 227 | # https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh 228 | Anaconda3-2024.06-1-Linux-x86_64.sh: sha256:539bb43d9a52d758d0fdfa1b1b049920ec6f8c6d15ee9fe4a423355fe551a8f7 229 | # https://repo.anaconda.com/archive/Anaconda3-2024.06-1-MacOSX-arm64.sh 230 | Anaconda3-2024.06-1-MacOSX-arm64.sh: sha256:f9e0795431910ee4ac341c0cc2a0b62e6c497440789b4117c20736db45b34204 231 | # https://repo.anaconda.com/archive/Anaconda3-2024.06-1-MacOSX-x86_64.sh 232 | Anaconda3-2024.06-1-MacOSX-x86_64.sh: sha256:9b2aa48bfc58e337176d8b5f3776692815807e1346ec12ebcc46a01801bb4ee0 233 | # https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Windows-x86_64.exe 234 | Anaconda3-2024.06-1-Windows-x86_64.exe: sha256:45eef9132b70e3d5a493c26429ddb4e2c9278a32097fd4bc729f860685633a3b 235 | --------------------------------------------------------------------------------