diff --git a/provision.yml b/provision.yml index 73752f6..43735c1 100644 --- a/provision.yml +++ b/provision.yml @@ -23,6 +23,7 @@ - windows-ad-controller roles: - windows-ad-controller + - { role: oatakan.chocolatey_package_localize, when: (local_chocolatey is defined and local_chocolatey|bool) } - name: Configure Windows Servers hosts: windows diff --git a/roles/oatakan.chocolatey_package_localize/.travis.yml b/roles/oatakan.chocolatey_package_localize/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/roles/oatakan.chocolatey_package_localize/LICENSE b/roles/oatakan.chocolatey_package_localize/LICENSE new file mode 100644 index 0000000..dc1b6e7 --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Orcun Atakan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/roles/oatakan.chocolatey_package_localize/README.md b/roles/oatakan.chocolatey_package_localize/README.md new file mode 100644 index 0000000..f5777d5 --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/README.md @@ -0,0 +1,107 @@ +# ansible-role-chocolatey_package_localize +Ansible role to localize chocolatey packages for Windows. + +With the defaults this role will: + +- Create c:\repo directory +- Set up SMB share giving access to Administrator user +- Download list of chocolately packages (.nupkg) locally + +The following can also be configured as part of the role but require some +chocolate_packages with url variable to be set: + +- For packages that depends on external binaries, you can provide url to download and repackage for local deployments. + +``` + chocolatey_packages: + - name: googlechrome + version: 77.0.3865.120 + url: https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi +``` + +> **_Note:_** This role is provided as an example only. Do not use this in production. You can fork/clone and add/remove steps for your environment based on your organization's security and operational requirements. + + +Requirements +------------ + +No special requirements. This role will run against a Windows server. + +Role Variables +-------------- + +### Mandatory Variables + +None, this role will run with the default options set. + +### Default Variables +* `chocolatey_repo_folder`: Directory to create and to store local packages. +* `chocolatey_internalize_packages`: whether to download binaries and repackage (default: true). +* `chocolatey_setup_shared_repo`: whether to setup a simple to use a repository for the clients (default: true). +* `chocolatey_share_name`: The name of the SBM share for the repo (default: repo). +* `chocolatey_share_description`: The description of the SBM share for the repo (default: nuget repo). +* `chocolatey_share_full_access`: The group/user name to give full access to SMB share for the repo (default: Administrator). +* `chocolatey_share_read_access`: The group/user name to give read access to SMB share for the repo (default: Administrator). +* `chocolatey_packages`: The list of packages in dictionary format: + +``` +chocolatey_packages: + - name: git.install + version: 2.23.0 + - name: googlechrome + version: 77.0.3865.120 + url: https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi +``` + +### Example + +Dependencies +------------ + +None + +Example Playbook +---------------- + + +``` +- name: localize packages + hosts: windows_server + gather_facts: no + roles: + - oatakan.chocolatey_package_localize + +- name: setup repo and install packages on clients + hosts: windows_clients + gather_facts: no + tasks: + - name: Add new internal source + win_chocolatey_source: + name: internal repo + state: present + source: '\\windows_server\repo' + priority: 1 + + - name: Install packages + win_chocolatey: + name: "{{ item }}" + loop: + - git.install + - googlechrome + vars: + ansible_become: yes + ansible_become_method: runas + ansible_become_user: '{{ ansible_user }}' + ansible_become_pass: '{{ ansible_password }}' +``` + +License +------- + +MIT + +Author Information +------------------ + +Orcun Atakan + diff --git a/roles/oatakan.chocolatey_package_localize/defaults/main.yml b/roles/oatakan.chocolatey_package_localize/defaults/main.yml new file mode 100644 index 0000000..1fd3524 --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/defaults/main.yml @@ -0,0 +1,16 @@ +--- + +chocolatey_repo_folder: 'C:\repo' +chocolatey_internalize_packages: true +chocolatey_setup_shared_repo: true +chocolatey_share_name: repo +chocolatey_share_description: nuget repo +chocolatey_share_full_access: Administrator +chocolatey_share_read_access: Administrator + +chocolatey_packages: + - name: git.install + version: 2.23.0 + - name: googlechrome + version: 77.0.3865.120 + url: https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi \ No newline at end of file diff --git a/roles/oatakan.chocolatey_package_localize/meta/main.yml b/roles/oatakan.chocolatey_package_localize/meta/main.yml new file mode 100644 index 0000000..ebee333 --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/meta/main.yml @@ -0,0 +1,23 @@ +--- +galaxy_info: + author: Orcun Atakan + description: Ansible galaxy role for internalizing Chocolatey packages for Windows. + role_name: chocolatey_package_localize + company: Red Hat + + license: MIT + + min_ansible_version: 2.8 + + platforms: + - name: Windows + versions: + - all + + galaxy_tags: + - windows + - chocolatey + - package + - internalize + +dependencies: [] diff --git a/roles/oatakan.chocolatey_package_localize/tasks/internalize.yml b/roles/oatakan.chocolatey_package_localize/tasks/internalize.yml new file mode 100644 index 0000000..c8c416b --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/tasks/internalize.yml @@ -0,0 +1,10 @@ +--- + +- name: check if package is already internalized + win_stat: + path: '{{ chocolatey_repo_folder }}\{{ package.name }}.{{ package.version }}.nupkg' + register: chocolatey_package_file + +- include_tasks: internalize_package.yml + when: + - not chocolatey_package_file.stat.exists \ No newline at end of file diff --git a/roles/oatakan.chocolatey_package_localize/tasks/internalize_package.yml b/roles/oatakan.chocolatey_package_localize/tasks/internalize_package.yml new file mode 100644 index 0000000..3953f7e --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/tasks/internalize_package.yml @@ -0,0 +1,87 @@ +--- + +- name: ensure temp package directory exists + win_file: + path: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}' + state: directory + +- name: ensure package exist locally with remote binary (<2.9) + win_get_url: + url: https://chocolatey.org/api/v2/package/{{ package.name }}/{{ package.version }} + dest: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}.nupkg.zip' + register: chocolatey_package_download + until: chocolatey_package_download is success + delay: 3 + retries: 5 + when: ansible_version.full is version('2.9', '<') + +- name: ensure package exist locally with remote binary + win_get_url: + url: https://chocolatey.org/api/v2/package/{{ package.name }}/{{ package.version }} + dest: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}.nupkg.zip' + follow_redirects: all + register: chocolatey_package_download + until: chocolatey_package_download is success + delay: 3 + retries: 5 + when: ansible_version.full is version('2.9', '>=') + +- name: unzip package file + win_unzip: + src: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}.nupkg.zip' + dest: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}' + delete_archive: yes + creates: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\tools' + +- name: delete extraneous files/folders + win_file: + path: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\{{ item }}' + state: absent + loop: + - '[Content_Types].xml' + - '_rels' + - 'package' + +- name: ensure binary file exist locally (<2.9) + win_get_url: + url: "{{ package.url }}" + dest: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\tools\{{ package.url | urlsplit("path") | basename }}' + register: chocolatey_binary_download + until: chocolatey_binary_download is success + delay: 3 + retries: 5 + when: ansible_version.full is version('2.9', '<') + +- name: ensure binary file exist locally + win_get_url: + url: "{{ package.url }}" + dest: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\tools\{{ package.url | urlsplit("path") | basename }}' + follow_redirects: all + register: chocolatey_binary_download + until: chocolatey_binary_download is success + delay: 3 + retries: 5 + when: ansible_version.full is version('2.9', '>=') + +- name: add file path + win_lineinfile: + path: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\tools\chocolateyInstall.ps1' + insertafter: '^ fileType ' + line: ' File64 = Get-Item $toolsPath\{{ package.url | urlsplit("path") | basename }}' + +- name: remove urls + win_lineinfile: + path: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\tools\chocolateyInstall.ps1' + regexp: '^ url' + state: absent + +- name: create package + win_shell: > + C:\ProgramData\chocolatey\choco pack -y + '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}\{{ package.name }}.nuspec' + --out='{{ chocolatey_repo_folder }}' + +- name: ensure temp directory is removed + win_file: + path: '{{ chocolatey_repo_folder }}\temp\{{ package.name }}.{{ package.version }}' + state: absent \ No newline at end of file diff --git a/roles/oatakan.chocolatey_package_localize/tasks/main.yml b/roles/oatakan.chocolatey_package_localize/tasks/main.yml new file mode 100644 index 0000000..9a18569 --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/tasks/main.yml @@ -0,0 +1,79 @@ +--- + +- name: ensure repo directory exists + win_file: + path: '{{ chocolatey_repo_folder }}' + state: directory + +- name: ensure share exists + win_share: + name: '{{ chocolatey_share_name }}' + description: '{{ chocolatey_share_description }}' + path: '{{ chocolatey_repo_folder }}' + list: yes + full: '{{ chocolatey_share_full_access }}' + read: '{{ chocolatey_share_read_access }}' + when: chocolatey_setup_shared_repo|bool + +- name: ensure packages exist locally (<2.9) + win_get_url: + url: https://chocolatey.org/api/v2/package/{{ item.name }}/{{ item.version }} + dest: '{{ chocolatey_repo_folder }}\{{ item.name }}.{{ item.version }}.nupkg' + loop: "{{ chocolatey_packages | selectattr('url', 'undefined') | list }}" + register: chocolatey_packages_1_download + until: chocolatey_packages_1_download is success + delay: 3 + retries: 5 + when: ansible_version.full is version('2.9', '<') + +- name: ensure packages exist locally + win_get_url: + url: https://chocolatey.org/api/v2/package/{{ item.name }}/{{ item.version }} + dest: '{{ chocolatey_repo_folder }}\{{ item.name }}.{{ item.version }}.nupkg' + follow_redirects: all + loop: "{{ chocolatey_packages | selectattr('url', 'undefined') | list }}" + register: chocolatey_packages_1_download + until: chocolatey_packages_1_download is success + delay: 3 + retries: 5 + when: ansible_version.full is version('2.9', '>=') + +- name: ensure packages exist locally with remote binary (<2.9) + win_get_url: + url: https://chocolatey.org/api/v2/package/{{ item.name }}/{{ item.version }} + dest: '{{ chocolatey_repo_folder }}\{{ item.name }}.{{ item.version }}.nupkg' + loop: "{{ chocolatey_packages | selectattr('url', 'defined') | list }}" + register: chocolatey_packages_2_download + until: chocolatey_packages_2_download is success + delay: 3 + retries: 5 + when: + - ansible_version.full is version('2.9', '<') + - not chocolatey_internalize_packages|bool + +- name: ensure packages exist locally with remote binary + win_get_url: + url: https://chocolatey.org/api/v2/package/{{ item.name }}/{{ item.version }} + dest: '{{ chocolatey_repo_folder }}\{{ item.name }}.{{ item.version }}.nupkg' + follow_redirects: all + loop: "{{ chocolatey_packages | selectattr('url', 'defined') | list }}" + register: chocolatey_packages_2_download + until: chocolatey_packages_2_download is success + delay: 3 + retries: 5 + when: + - ansible_version.full is version('2.9', '>=') + - not chocolatey_internalize_packages|bool + +- block: + - name: install Chocolatey + win_chocolatey: + name: chocolatey + state: present + + - name: internalize packages + include_tasks: internalize.yml + loop: "{{ chocolatey_packages | selectattr('url', 'defined') | list }}" + loop_control: + loop_var: package + when: chocolatey_internalize_packages|bool \ No newline at end of file diff --git a/roles/oatakan.chocolatey_package_localize/tests/inventory b/roles/oatakan.chocolatey_package_localize/tests/inventory new file mode 100644 index 0000000..d18580b --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/tests/inventory @@ -0,0 +1 @@ +localhost \ No newline at end of file diff --git a/roles/oatakan.chocolatey_package_localize/tests/test.yml b/roles/oatakan.chocolatey_package_localize/tests/test.yml new file mode 100644 index 0000000..2c0141f --- /dev/null +++ b/roles/oatakan.chocolatey_package_localize/tests/test.yml @@ -0,0 +1,7 @@ +--- +- hosts: localhost + gather_facts: False + connection: local + become: no + roles: + - ../. \ No newline at end of file diff --git a/roles/windows-workstation/tasks/main.yml b/roles/windows-workstation/tasks/main.yml index 22eb259..6480424 100644 --- a/roles/windows-workstation/tasks/main.yml +++ b/roles/windows-workstation/tasks/main.yml @@ -14,12 +14,20 @@ state: disabled when: ansible_version.full is version_compare('2.8', '<') - - name: Install Visual Studio Code, Git, and Putty + - name: Add new internal source + win_chocolatey_source: + name: internal repo + state: present + source: '\\windc\repo' + priority: 1 + when: local_chocolatey is defined and local_chocolatey|bool + + - name: Install Visual Studio Code, Git, and Google Chrome win_chocolatey: name: "{{ item }}" ignore_checksums: true with_items: - - visualstudiocode + - vscode - git - googlechrome register: chocolatey_packages_install diff --git a/vars/main.yml b/vars/main.yml index df03047..714c007 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -49,6 +49,25 @@ nginx_ssl: true windows_ansible_connection: winrm # set this to winrm/ssh windows_openssh_url: https://github.com/PowerShell/Win32-OpenSSH/releases/download/v8.0.0.0p1-Beta/OpenSSH-Win64.zip +# Chocolatey packages +local_chocolatey: false +chocolatey_share_read_access: Ansible Users +chocolatey_packages: + - name: chocolatey-core.extension + version: 1.3.3 + - name: dotnet4.5.2 + version: 4.5.2.20140902 + - name: git.install + version: 2.23.0 + - name: git + version: 2.23.0 + - name: googlechrome + version: 77.0.3865.120 + url: https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi + - name: vscode + version: 1.39.0 + url: https://az764295.vo.msecnd.net/stable/9df03c6d6ce97c6645c5846f6dfa2a6a7d276515/VSCodeSetup-x64-1.39.0.exe + ########################################################## ###################### GITLAB INFO ####################### ##########################################################