├── .ansible-lint ├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── issue--bug-report.yml │ └── issue--feature-request.yml ├── dependabot.yml ├── release-drafter.yml └── workflows │ ├── conventional-commits.yml │ ├── draft-release.yml │ ├── linter-analysis.yaml │ ├── semvar.yml │ └── stale-updater.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ContributorAgreement.txt ├── Dockerfile ├── LICENSE ├── README.md ├── SUPPORT.md ├── ansible.cfg ├── docker-entrypoint.sh ├── docs ├── CONFIG-VARS.md ├── Troubleshooting.md ├── community │ ├── README.md │ └── community-config-vars.md └── user │ ├── AnsibleCloudAuthentication.md │ ├── AnsibleUsage.md │ ├── Dependencies.md │ ├── DeploymentDirectoryStructure.md │ ├── DockerUsage.md │ ├── DockerVolumeMounts.md │ ├── Kubeconfig.md │ ├── NetworkingConsiderations.md │ ├── PostgreSQL.md │ ├── SingleStore.md │ ├── ThirdPartyComponents.md │ └── TrustedCACerts.md ├── examples ├── ansible-vars-iac.yaml ├── ansible-vars.yaml ├── multi-tenancy │ ├── ansible-vars-multi-tenancy.yaml │ └── openldap │ │ └── openldap-modify-mt-users-groups.yaml ├── openldap │ └── openldap-modify-users.yaml ├── sitedefault.yaml └── sssd.conf ├── linting-configs ├── .ansible-lint ├── .hadolint.yaml └── .shellcheckrc ├── playbooks ├── README.md └── playbook.yaml ├── requirements.txt ├── requirements.yaml └── roles ├── baseline ├── defaults │ └── main.yml └── tasks │ ├── cert-manager.yaml │ ├── cluster-autoscaler.yaml │ ├── contour.yaml │ ├── ebs-csi-driver.yaml │ ├── ingress-nginx.yaml │ ├── main.yaml │ ├── metrics-server.yaml │ ├── nfs-csi-provisioner.yaml │ └── storage-classes.yaml ├── common ├── defaults │ └── main.yml ├── lookup_plugins │ └── tfstate.py └── tasks │ ├── main.yaml │ ├── migrations.yaml │ └── task-validations.yaml ├── istio ├── README.md ├── defaults │ └── main.yml ├── tasks │ └── main.yml ├── templates │ ├── grafana-secret.yaml │ └── kiali-secret.yaml ├── tests │ ├── inventory │ └── test.yml └── vars │ └── main.yml ├── jump-server ├── defaults │ └── main.yml └── tasks │ └── main.yml ├── multi-tenancy ├── defaults │ └── main.yml ├── tasks │ ├── main.yaml │ ├── multi-tenant-onboard-offboard.yaml │ ├── multi-tenant-setup.yaml │ ├── onboard-offboard-cas-servers.yaml │ ├── tenant-cas-customizations.yaml │ └── tenant-pod-templates.yaml └── templates │ ├── cas-enable-external-services.yaml │ └── cas-manage-cpu-and-memory.yaml ├── orchestration-common ├── defaults │ └── main.yaml └── tasks │ └── orchestration_tooling.yaml └── vdm ├── defaults └── main.yaml ├── files ├── sitedefault-mt.yaml └── sitedefault.yaml ├── library ├── overlay_facts.py └── siteconfig_info.py ├── tasks ├── assets.yaml ├── cas.yaml ├── connect.yaml ├── copy_overlay.yaml ├── deploy.yaml ├── deployment_operator.yaml ├── elasticsearch.yaml ├── kustomize.yaml ├── main.yaml ├── mirror.yaml ├── multi_tenant.yaml ├── postgres │ ├── gcp-cloud-sql-proxy.yaml │ ├── pg_config.yaml │ ├── postgres-instance.yaml │ ├── postgres-multi-tenant-config.yaml │ └── postgres.yaml ├── sasdeployment_custom_resource.yaml ├── sizing.yaml ├── start_stop.yaml ├── storage.yaml ├── tls.yaml └── workload_orchestrator.yaml ├── templates ├── cr_access.json ├── deployment-operator-clusterwide.yaml ├── deployment_operator_kustomization.yaml ├── generators │ ├── customer-provided-ca-certificates.yaml │ ├── customer-provided-ingress-certificate.yaml │ ├── customer-provided-merge-sas-certframe-configmap.yaml │ ├── ingress-input.yaml │ ├── mirror.v2.yaml │ ├── mirror.yaml │ ├── openldap-bootstrap-config.yaml │ ├── openldap-bootstrap-mt-config.yaml │ ├── postgres-config.yaml │ ├── postgres-sas-user.yaml │ ├── postgres-secrets.yaml │ ├── sas-consul-config-secret.yaml │ ├── sas-consul-config.yaml │ ├── sas-go-config.yaml │ ├── sas-image-pull-secrets.yaml │ ├── sas-license.yaml │ ├── sas-postgres-config.v2.yaml │ ├── sas-postgres-config.yaml │ ├── sas-shared-config.yaml │ ├── sas-sssd-config.yaml │ └── sql-proxy-serviceaccountkey.yaml ├── kustomization.yaml ├── postgres-user.env ├── resources │ ├── cloud-sql-proxy-instance.yaml │ ├── consul-ui.yaml │ ├── openldap.yaml │ ├── openssl-generated-ingress-certificate.yaml │ ├── platform-postgres-dataserver.yaml │ ├── postgres-instance.yaml │ ├── sas-connect-spawner-enable-loadbalancer.yaml │ └── sas-deployment-buildinfo.yaml └── transformers │ ├── cas-add-nfs-mount.yaml │ ├── cas-auto-restart.yaml │ ├── cas-enable-external-services.yaml │ ├── cas-manage-backup.yaml │ ├── cas-manage-cpu-and-memory.yaml │ ├── cas-manage-workers.yaml │ ├── cas-sssd.yaml │ ├── cert-manager-provided-ingress-certificate.yaml │ ├── compute-server-add-nfs-mount.v2.yaml │ ├── compute-server-add-nfs-mount.yaml │ ├── crunchy-storage-transformer.yaml │ ├── dataserver-transformer.yaml │ ├── launcher-nfs-mount.yaml │ ├── launcher-service-add-nfs.yaml │ ├── nginx-ingressclass.yaml │ ├── openldap.yaml │ ├── postgres-storage-transformer.v2.yaml │ ├── postgres-storage-transformer.v3.yaml │ ├── postgres-storage-transformer.yaml │ ├── rabbitmq-transformer.yaml │ ├── sas-storageclass.yaml │ └── schedule-start-stop.yaml └── vars └── main.yaml /.ansible-lint: -------------------------------------------------------------------------------- 1 | var_naming_pattern: "^[a-zA-Z0-9_]*$" 2 | 3 | parseable: true 4 | 5 | exclude_paths: 6 | - .git/ 7 | - .gitignore 8 | - .cache/ 9 | - roles/istio 10 | 11 | skip_list: 12 | - unnamed-task 13 | - role-name 14 | - var-naming 15 | 16 | warn_list: 17 | - experimental 18 | - no-changed-when 19 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | docs/ 2 | *.md 3 | *.txt 4 | !requirements.txt 5 | *.log 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue--bug-report.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | description: | 4 | Welcome, Thanks for opening an issue. The more information you provide, the easier it is for us to assess the problem, prioritize, assign, develop, then release a fix. The SAS Viya 4 IaC team. 5 | labels: [bug, new] 6 | body: 7 | - type: textarea 8 | id: dac_version 9 | attributes: 10 | label: Viya4 Deployment Version Details 11 | description: | 12 | We ask this to know which version of viya4-deployment you are running from your work environment. 13 | 14 | If you are not running the latest version of viya4-deployment, please try upgrading because your issue may have already been fixed. 15 | 16 | If you're not sure what the latest version is, here's a link to the releases: https://github.com/sassoftware/viya4-deployment/releases 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: dac_vars 21 | attributes: 22 | label: Ansible Variable File Details 23 | description: | 24 | Paste the relevant parts of your ansible-vars.yaml variables file or variable flag values here. 25 | 26 | The relevant parts should come from your `ansible-vars.yaml` file or equivalent that seem to be causing the error. 27 | 28 | For security reasons, do not copy and paste any sensitive information in this issue, like account information and passwords etc. 29 | validations: 30 | required: false 31 | - type: textarea 32 | id: dac_steps_to_reproduce 33 | attributes: 34 | label: Steps to Reproduce 35 | description: Please list the full steps required to reproduce the issue including the docker run or ansible-playbook command used that reproduces the issue. 36 | validations: 37 | required: true 38 | - type: textarea 39 | id: dac_expected_behavior 40 | attributes: 41 | label: Expected Behavior 42 | description: What should have happened? 43 | validations: 44 | required: true 45 | - type: textarea 46 | id: dac_actual_behavior 47 | attributes: 48 | label: Actual Behavior 49 | description: | 50 | What actually happened? Here you can include output and information from your viya4-deployment run. 51 | validations: 52 | required: true 53 | - type: textarea 54 | id: dac_additional_context 55 | attributes: 56 | label: Additional Context 57 | description: | 58 | Is there anything atypical about your situation that we should know? For example: Are you passing any unusual command line options or environment variables to opt-in to non-default behavior? 59 | validations: 60 | required: false 61 | - type: input 62 | id: dac_references 63 | attributes: 64 | label: References 65 | description: | 66 | Are there any other GitHub issues (open or closed) or Pull Requests that should be linked here? Before you create a new issue, please do a search in open [issues](https://github.com/sassoftware/viya4-deployment/issues) to see if a similar issue or feature request has already been filed. 67 | validations: 68 | required: false 69 | - type: checkboxes 70 | id: dac_terms 71 | attributes: 72 | label: Code of Conduct 73 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sassoftware/viya4-deployment/blob/main/CODE_OF_CONDUCT.md) 74 | options: 75 | - label: I agree to follow this project's Code of Conduct 76 | required: true 77 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue--feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: | 3 | Welcome, Thanks for opening a feature request. The more information you provide, the easier it is for us to assess your request, prioritize, assign, develop, and release. The SAS Viya 4 IaC team. 4 | labels: [enhancement, new] 5 | body: 6 | - type: textarea 7 | id: problem 8 | attributes: 9 | label: Is your feature request related to a problem? Please describe. 10 | description: | 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | validations: 13 | required: true 14 | - type: textarea 15 | id: solution 16 | attributes: 17 | label: Describe the solution you'd like 18 | description: | 19 | A clear and concise description of what you want to happen. 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: alternatives 24 | attributes: 25 | label: Describe alternatives you've considered 26 | description: | 27 | A clear and concise description of any alternative solutions or features you've considered. 28 | validations: 29 | required: false 30 | - type: textarea 31 | id: additional 32 | attributes: 33 | label: Additional context 34 | description: Add any other context or screenshots about the feature request here. 35 | validations: 36 | required: false 37 | - type: checkboxes 38 | id: tf_terms 39 | attributes: 40 | label: Code of Conduct 41 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sassoftware/viya4-deployment/blob/main/CODE_OF_CONDUCT.md) 42 | options: 43 | - label: I agree to follow this project's Code of Conduct 44 | required: true 45 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Terraform dependencies 4 | - package-ecosystem: "terraform" 5 | directory: "/" # The directory where your Terraform files are located 6 | schedule: 7 | interval: "weekly" 8 | target-branch: "main" 9 | open-pull-requests-limit: 2 10 | 11 | # Docker dependencies 12 | - package-ecosystem: "docker" 13 | directory: "/" # The directory where your Dockerfile is located 14 | schedule: 15 | interval: "weekly" 16 | target-branch: "main" 17 | open-pull-requests-limit: 2 18 | 19 | # GitHub Actions dependencies 20 | - package-ecosystem: "github-actions" 21 | directory: "/" # The directory where your GitHub Actions workflows are located 22 | schedule: 23 | interval: "weekly" 24 | target-branch: "main" 25 | open-pull-requests-limit: 2 26 | 27 | # Python dependencies (from requirements.txt) 28 | - package-ecosystem: "pip" 29 | directory: "/" # The directory where your requirements.txt is located 30 | schedule: 31 | interval: "weekly" 32 | target-branch: "main" 33 | open-pull-requests-limit: 2 34 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION - ' 2 | tag-template: 'v$RESOLVED_VERSION' 3 | categories: 4 | - title: '⚠️ BREAKING CHANGES' 5 | labels: 6 | - 'breaking change' 7 | - title: '🚀 Features' 8 | labels: 9 | - 'feature' 10 | - 'enhancement' 11 | - title: '🐛 Bug Fixes' 12 | labels: 13 | - 'bug' 14 | - title: '📖 Documentation' 15 | labels: 16 | - 'documentation' 17 | - title: '⏱️ Performance' 18 | labels: 19 | - 'performance' 20 | - title: '🤖 Tests' 21 | labels: 22 | - 'test' 23 | - title: '🔧 Maintenance' 24 | labels: 25 | - 'build' 26 | - 'chore' 27 | - 'CI/CD' 28 | - 'refactor' 29 | - 'revert' 30 | - 'style' 31 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 32 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 33 | version-resolver: 34 | major: 35 | labels: 36 | - 'breaking change' 37 | minor: 38 | labels: 39 | - 'feature' 40 | - 'enhancement' 41 | patch: 42 | labels: 43 | - 'bug' 44 | - 'CI/CD' 45 | - 'documentation' 46 | - 'test' 47 | - 'performance' 48 | - 'refactor' 49 | - 'chore' 50 | - 'revert' 51 | - 'style' 52 | default: patch 53 | template: | 54 | ## Changes 55 | 56 | $CHANGES 57 | 58 | **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION 59 | -------------------------------------------------------------------------------- /.github/workflows/conventional-commits.yml: -------------------------------------------------------------------------------- 1 | name: PR Conventional Commit Validation 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, edited] 6 | branches: 7 | - main 8 | 9 | jobs: 10 | validate-pr-title: 11 | runs-on: ubuntu-latest 12 | steps: 13 | # https://github.com/marketplace/actions/conventional-commit-in-pull-requests 14 | - name: PR Conventional Commit Validation 15 | uses: ytanikin/pr-conventional-commits@1.4.0 16 | with: 17 | task_types: '["fix", "feat", "build", "chore", "ci", "docs", "style", "refactor", "perf", "test"]' 18 | custom_labels: '{"feat": "enhancement", "fix": "bug", "docs": "documentation", "ci": "CI/CD", "perf": "performance"}' -------------------------------------------------------------------------------- /.github/workflows/draft-release.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | update_release_draft: 13 | permissions: 14 | # write permission is required to create a github release 15 | contents: write 16 | runs-on: ubuntu-latest 17 | steps: 18 | # Drafts your next Release notes as Pull Requests are merged into "main" 19 | - uses: release-drafter/release-drafter@v6 20 | with: 21 | disable-autolabeler: true 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /.github/workflows/linter-analysis.yaml: -------------------------------------------------------------------------------- 1 | name: Linter Analysis 2 | on: 3 | push: 4 | branches: [ '**' ] # '*' will cause the workflow to run on all commits to all branches. 5 | 6 | jobs: 7 | # Hadolint: Job-1 8 | Hadolint: 9 | name: Hadolint 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout Repo 13 | uses: actions/checkout@v4 14 | 15 | - name: Run Hadolint Action 16 | uses: jbergstroem/hadolint-gh-action@v1.12.2 17 | with: 18 | dockerfile: ./Dockerfile 19 | config_file: linting-configs/.hadolint.yaml 20 | error_level: 1 # Fail CI based on hadolint output (-1: never, 0: error, 1: warning, 2: info) 21 | 22 | # ShellCheck: Job-2 23 | ShellCheck: 24 | name: ShellCheck 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: Checkout Repo 28 | uses: actions/checkout@v4 29 | 30 | # .shellcheckrc is read from the current dir 31 | - name: Copy Config to Parent Level Directory 32 | run: cp $(pwd)/linting-configs/.shellcheckrc . 33 | 34 | - name: Run ShellCheck Action 35 | uses: ludeeus/action-shellcheck@master 36 | with: 37 | severity: error 38 | 39 | # ansible-lint: Job-3 40 | Ansible-Lint: 41 | name: ansible-lint 42 | runs-on: ubuntu-latest 43 | steps: 44 | - name: Checkout Repo 45 | uses: actions/checkout@v4 46 | 47 | # The latest ansible/ansible-lint-action removed the 48 | # ability to specify configs from other dirs 49 | - name: Copy Config to Parent Level Directory 50 | run: cp $(pwd)/linting-configs/.ansible-lint . 51 | 52 | # ansible-lint does not seem to recognize the .yaml 53 | # extension for the requirements file and it is not 54 | # configurable 55 | - name: Updates requirements extension 56 | run: cp $(pwd)/requirements.yaml requirements.yml 57 | 58 | - name: Install requirements.yaml 59 | run: ansible-galaxy install -r ./requirements.yaml 60 | 61 | - name: Run ansible-lint Action 62 | uses: ansible/ansible-lint-action@v6.17.0 63 | env: 64 | ANSIBLE_ROLES_PATH: "./roles" 65 | -------------------------------------------------------------------------------- /.github/workflows/semvar.yml: -------------------------------------------------------------------------------- 1 | name: Update Semver 2 | on: 3 | push: 4 | branches-ignore: 5 | - '**' 6 | tags: 7 | - 'v*.*.*' 8 | jobs: 9 | update-semver: 10 | # Update the tags based on semantic versioning. 11 | # Also update the latest tag. 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: haya14busa/action-update-semver@v1 16 | - name: Create latest git tag 17 | run: | 18 | git tag latest 19 | - name: Push latest git tag 20 | run: git push -f origin latest -------------------------------------------------------------------------------- /.github/workflows/stale-updater.yaml: -------------------------------------------------------------------------------- 1 | name: 'Mark stale issues and PRs' 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v9.1.0 11 | with: 12 | stale-issue-message: 'This issue is stale because it has been open 30 days with no activity.' 13 | stale-pr-message: 'This PR is stale because it has been open 30 days with no activity.' 14 | days-before-stale: 30 15 | days-before-close: -1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## ignore log files 2 | *.log 3 | 4 | ## ignore galaxy_install_info 5 | .galaxy_install_info 6 | 7 | ## ignore ansible-vars.yml 8 | ansible-vars.yml 9 | ansible-vars.yaml 10 | 11 | ## ignore data directory 12 | data/ 13 | 14 | .DS_Store 15 | 16 | # Environments 17 | .env 18 | .venv 19 | env/ 20 | venv/ 21 | ENV/ 22 | env.bak/ 23 | venv.bak/ 24 | 25 | # Byte-compiled / optimized / DLL files 26 | __pycache__/ 27 | *.py[cod] 28 | *$py.class 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | We'd love to accept your patches and contributions to this project. 3 | We just ask that you follow our contribution guidelines when you do. 4 | 5 | ## Contributor License Agreement 6 | Contributions to this project must be accompanied by a signed [Contributor Agreement](ContributorAgreement.txt). 7 | You (or your employer) retain the copyright to your contribution; this simply grants us permission to use and redistribute your contributions as part of the project. 8 | 9 | ## Code Reviews 10 | All submissions to this project—including submissions from project members—require 11 | review. Our review process typically involves performing unit tests, development 12 | tests, integration tests, and security scans. 13 | 14 | ## How To Open A Pull Request 15 | 16 | The following steps below demonstrate how to contribute to the [viya4-deployment](https://github.com/sassoftware/viya4-deployment) 17 | repository by forking it, making changes, and submitting a pull request (PR). 18 | 19 | 1. Fork the Repository 20 | 21 | - Navigate to the [viya4-deployment](https://github.com/sassoftware/viya4-deployment). 22 | - Click the **“Fork”** button in the upper-right corner. 23 | - This creates a copy of the repository under your GitHub account. 24 | 25 | **Alternative (using GitHub CLI):** 26 | If you have the [GitHub CLI](https://cli.github.com/) installed, run: 27 | 28 | ```bash 29 | gh repo fork https://github.com/sassoftware/viya4-deployment.git --clone 30 | ``` 31 | 32 | 2. Clone the Forked Repository Locally 33 | 34 | ```bash 35 | git clone https://github.com//.git 36 | ``` 37 | 38 | 3. Add the Original Repository as an Upstream Remote (Optional but recommended) 39 | 40 | - To keep your fork in sync with the original [viya4-deployment](https://github.com/sassoftware/viya4-deployment) 41 | repository: 42 | 43 | ```bash 44 | git remote add upstream https://github.com/sassoftware/viya4-deployment.git 45 | git fetch upstream 46 | ``` 47 | 48 | - To sync changes from the original repo: 49 | 50 | ```bash 51 | git checkout main 52 | git pull upstream main 53 | git push origin main 54 | ``` 55 | 56 | 4. Create a New Branch for Your Contribution 57 | 58 | ```bash 59 | git checkout -b my-contribution-branch 60 | ``` 61 | 62 | 5. Make Your Changes Locally 63 | 64 | - Edit the files as needed using your preferred code editor. 65 | 66 | 6. Stage and Commit Your Changes 67 | 68 | ```bash 69 | git add . 70 | git commit -s -m "Your conventional commit message" 71 | ``` 72 | 73 | 7. Push the Branch to Your Fork 74 | 75 | ```bash 76 | git push origin my-contribution-branch 77 | ``` 78 | 79 | 8. Create the Pull Request (PR) 80 | 81 | - Go to your forked repository on GitHub. 82 | - You will see a **“Compare & pull request”** button, click it. 83 | - Check to ensure: 84 | - The **base repository** is the original [viya4-deployment](https://github.com/sassoftware/viya4-deployment) 85 | repository. 86 | - The **base branch** is `main`. 87 | - The **head repository** and **compare branch** is correct. 88 | - Click **“Create pull request.”** 89 | 90 | 9. Keep Your Branch Up to Date (If Needed) 91 | 92 | - If the base branch has changed and you need to rebase: 93 | 94 | ```bash 95 | git fetch upstream 96 | git checkout my-contribution-branch 97 | git rebase upstream/main 98 | ``` 99 | 100 | - After resolving any conflicts, force push your changes: 101 | 102 | ```bash 103 | git push origin my-contribution-branch --force 104 | ``` 105 | 106 | ## Pull Request Requirement 107 | 108 | ### Conventional Commits 109 | All pull requests must follow the [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) 110 | standard for commit messages. This helps maintain a consistent and meaningful 111 | commit history. Pull requests with commits that do not follow the Conventional 112 | Commit format will not be merged. 113 | 114 | ### Developer Certificate of Origin Sign-Off 115 | This project requires all commits to be signed off in accordance with the [Developer Certificate of Origin (DCO)](https://developercertificate.org/). 116 | By signing off your commits, you certify that you have the right to submit the 117 | contribution under the open source license used by this project. 118 | 119 | To sign off your commits, use the --signoff flag with git commit: 120 | 121 | ```bash 122 | git commit --signoff -m "Your commit message" 123 | ``` 124 | 125 | This will add a Signed-off-by line to your commit message, e.g.: 126 | 127 | ```bash 128 | Signed-off-by: You Name 129 | ``` 130 | 131 | For more information, please refer to https://probot.github.io/apps/dco/ 132 | 133 | ### Linter Analysis Checks 134 | All pull requests must pass our automated analysis checks before they can be 135 | merged. These checks include: 136 | 137 | - **Hadolint** – for Dockerfile best practices 138 | - **ShellCheck** – for shell script issues 139 | - **Ansible-lint** – for Ansible playbook and role validation 140 | 141 | ## Security Scans 142 | To ensure that all submissions meet our security and quality standards, we perform 143 | security scans using internal SAS infrastructure. Contributions might be subjected 144 | to security scans before they can be accepted. Reporting of any Common Vulnerabilities 145 | and Exposures (CVEs) that are detected is not available in this project at this 146 | time. 147 | -------------------------------------------------------------------------------- /ContributorAgreement.txt: -------------------------------------------------------------------------------- 1 | Contributor Agreement 2 | 3 | Version 1.1 4 | 5 | Contributions to this software are accepted only when they are 6 | properly accompanied by a Contributor Agreement. The Contributor 7 | Agreement for this software is the Developer's Certificate of Origin 8 | 1.1 (DCO) as provided with and required for accepting contributions 9 | to the Linux kernel. 10 | 11 | In each contribution proposed to be included in this software, the 12 | developer must include a "sign-off" that denotes consent to the 13 | terms of the Developer's Certificate of Origin. The sign-off is 14 | a line of text in the description that accompanies the change, 15 | certifying that you have the right to provide the contribution 16 | to be included. For changes provided in source code control (for 17 | example, via a Git pull request) the sign-off must be included in 18 | the commit message in source code control. For changes provided 19 | in email or issue tracking, the sign-off must be included in the 20 | email or the issue, and the sign-off will be incorporated into the 21 | permanent commit message if the contribution is accepted into the 22 | official source code. 23 | 24 | If you can certify the below: 25 | 26 | Developer's Certificate of Origin 1.1 27 | 28 | By making a contribution to this project, I certify that: 29 | 30 | (a) The contribution was created in whole or in part by me and I 31 | have the right to submit it under the open source license 32 | indicated in the file; or 33 | 34 | (b) The contribution is based upon previous work that, to the best 35 | of my knowledge, is covered under an appropriate open source 36 | license and I have the right under that license to submit that 37 | work with modifications, whether created in whole or in part 38 | by me, under the same open source license (unless I am 39 | permitted to submit under a different license), as indicated 40 | in the file; or 41 | 42 | (c) The contribution was provided directly to me by some other 43 | person who certified (a), (b) or (c) and I have not modified 44 | it. 45 | 46 | (d) I understand and agree that this project and the contribution 47 | are public and that a record of the contribution (including all 48 | personal information I submit with it, including my sign-off) is 49 | maintained indefinitely and may be redistributed consistent with 50 | this project or the open source license(s) involved. 51 | 52 | then you just add a line saying 53 | 54 | Signed-off-by: Random J Developer 55 | 56 | using your real name (sorry, no pseudonyms or anonymous contributions.) -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:experimental 2 | FROM ubuntu:22.04 AS baseline 3 | 4 | RUN apt-get update && apt-get upgrade -y \ 5 | && apt-get install --no-install-recommends -y python3 python3-dev python3-pip curl unzip apt-transport-https ca-certificates gnupg \ 6 | && apt-get clean \ 7 | && rm -rf /var/lib/apt/lists/* \ 8 | && update-alternatives --install /usr/bin/python python /usr/bin/python3 1 \ 9 | && update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 10 | 11 | FROM baseline AS tool_builder 12 | ARG kubectl_version=1.31.7 13 | 14 | WORKDIR /build 15 | 16 | RUN curl -sLO https://dl.k8s.io/release/v$kubectl_version/bin/linux/amd64/kubectl && chmod 755 ./kubectl 17 | 18 | # Build Skopeo from source since the version in the apt repository is outdated 19 | FROM golang:alpine3.20 AS golang 20 | ARG SKOPEO_VERSION=release-1.16 21 | RUN apk add --no-cache git build-base containers-common bash btrfs-progs-dev glib-dev go go-md2man gpgme-dev libselinux-dev linux-headers lvm2-dev ostree-dev \ 22 | && git clone https://github.com/containers/skopeo.git -b $SKOPEO_VERSION \ 23 | && DISABLE_DOCS=1 make -C skopeo bin/skopeo.linux.386 24 | 25 | # Installation 26 | FROM baseline 27 | ARG helm_version=3.17.1 28 | ARG aws_cli_version=2.24.16 29 | ARG gcp_cli_version=513.0.0-0 30 | 31 | # Add extra packages 32 | RUN apt-get update && apt-get install --no-install-recommends -y gzip wget git jq ssh sshpass rsync \ 33 | && rm -f /etc/ssh/ssh_host_rsa_key && rm -f /etc/ssh/ssh_host_ecdsa_key && rm -f /etc/ssh/ssh_host_ed25519_key \ 34 | && curl -ksLO https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 && chmod 755 get-helm-3 \ 35 | && ./get-helm-3 --version v$helm_version --no-sudo \ 36 | # AWS 37 | && architecture=$(uname -m) \ 38 | && curl "https://awscli.amazonaws.com/awscli-exe-linux-${architecture}-${aws_cli_version}.zip" -o "awscliv2.zip" \ 39 | && unzip awscliv2.zip \ 40 | && ./aws/install \ 41 | # AZURE 42 | && curl -sL https://aka.ms/InstallAzureCLIDeb | bash \ 43 | # GCP 44 | && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \ 45 | && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \ 46 | && apt-get update && apt-get install --no-install-recommends -y google-cloud-cli:*=${gcp_cli_version} \ 47 | && apt-get install --no-install-recommends -y google-cloud-sdk-gke-gcloud-auth-plugin \ 48 | && apt-get clean \ 49 | && rm -rf /var/lib/apt/lists/* 50 | 51 | COPY --from=tool_builder /build/kubectl /usr/local/bin/kubectl 52 | COPY --from=golang /go/skopeo/bin/skopeo.linux.386 /usr/local/bin/skopeo 53 | 54 | WORKDIR /viya4-deployment/ 55 | COPY . /viya4-deployment/ 56 | 57 | ENV HOME=/viya4-deployment 58 | 59 | RUN pip install -r ./requirements.txt \ 60 | && ansible-galaxy install -r ./requirements.yaml \ 61 | && rm -rf /usr/local/lib/python3.10/dist-packages/ansible_collections/infinidat \ 62 | && rm -rf /usr/local/lib/python3.10/dist-packages/ansible_collections/netbox \ 63 | && pip cache purge \ 64 | && chmod -R g=u /etc/passwd /etc/group /viya4-deployment/ \ 65 | && chmod 755 /viya4-deployment/docker-entrypoint.sh \ 66 | && git config --system --add safe.directory /viya4-deployment ||: 67 | 68 | ENV PLAYBOOK=playbook.yaml 69 | ENV VIYA4_DEPLOYMENT_TOOLING=docker 70 | ENV ANSIBLE_CONFIG=/viya4-deployment/ansible.cfg 71 | 72 | VOLUME ["/data", "/config", "/vault"] 73 | ENTRYPOINT ["/viya4-deployment/docker-entrypoint.sh"] 74 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | ## Support 2 | 3 | We use GitHub for tracking bugs and feature requests. Please submit a GitHub issue or pull request for support. -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null 3 | pipelining = True 4 | 5 | [defaults] 6 | # log_path = ./ansible.log 7 | roles_path = ./roles 8 | remote_tmp = $HOME/.ansible/tmp 9 | local_tmp = $HOME/.ansible/tmp 10 | gathering = smart 11 | host_key_checking = False 12 | deprecation_warnings = False 13 | inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds 14 | localhost_warning = False 15 | inventory = /dev/null 16 | callbacks_enabled = profile_tasks 17 | display_skipped_hosts = False 18 | hash_behaviour=merge 19 | library = /usr/share/ansible:./plugins/modules 20 | lookup_plugins = ./plugins/lookup 21 | action_plugins = ./plugins/action 22 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | set -e 7 | 8 | # setup container user 9 | echo "viya4-deployment:*:$(id -u):$(id -g):,,,:/viya4-deployment:/bin/bash" >> /etc/passwd 10 | echo "viya4-deployment:*:$(id -G | cut -d' ' -f 2)" >> /etc/group 11 | 12 | OPTS="-e BASE_DIR=/data" 13 | 14 | for MOUNT in "/config"/* 15 | do 16 | base=$(basename $MOUNT) 17 | VAR=${base^^} 18 | 19 | if [[ "$VAR" == "VAULT_PASSWORD_FILE" ]]; then 20 | OPTS+=" --vault-password-file $MOUNT" 21 | else 22 | OPTS+=" -e $VAR=$MOUNT" 23 | fi 24 | done 25 | 26 | # TODO: Can remove the next line when the default GKE kubernetes_version is moved to 1.26 and greater 27 | export USE_GKE_GCLOUD_AUTH_PLUGIN=True 28 | echo "Running: ansible-playbook $OPTS $@ playbooks/${PLAYBOOK}" 29 | ANSIBLE_STDOUT_CALLBACK=yaml exec ansible-playbook $OPTS $@ playbooks/${PLAYBOOK} 30 | -------------------------------------------------------------------------------- /docs/community/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Community-Contributed Features 3 | 4 | Community contributed features are submitted by community members to help expand the set of features that the project maintainers are capable of adding to the project on their own. 5 | 6 | > [!CAUTION] 7 | > Community members are responsible for maintaining these features. While project maintainers try to verify these features work as expected when merged, they cannot guarantee future releases will not break them. If you encounter issues while using these features, start a [GitHub Discussion](https://github.com/sassoftware/viya4-deployment/discussions) or open a Pull Request to fix them. As a last resort, create a GitHub Issue for the concern. 8 | 9 | ## Community-Contributed Feature Expectations 10 | 11 | - As with other features, community contributed features should include unit tests which add to the level of community confidence for the feature. Unit tests should also help indicate if a problem occurs with the feature in a future release. 12 | 13 | - Community contributed features should be disabled by default. If applicable, a boolean configuration variable named COMMUNITY_ENABLE_ should be implemented for the community feature. The boolean configuration variable should serve as a way to enable or disable the community feature. 14 | 15 | - Multiple community contributed feature configuration variables may exist for the same feature, although if the feature is disabled, they should have no effect on the overall behavior of the project. 16 | 17 | - Additional community contributed feature configuration variables should use the COMMUNITY_ prefix to indicate they are part of a community contributed feature. 18 | 19 | ## Submitting a Community-Contributed Feature 20 | 21 | Submit a community contributed Feature by creating a GitHub PR in this project. The PR should include the source code, unit tests and any required documentation including expected content for the [docs/community/community-config-vars.md](community-config-vars.md) file. 22 | 23 | ## What if a Community-Contributed Feature breaks 24 | 25 | If you encounter issues while using a community contributed feature, start a [GitHub Discussion](https://github.com/sassoftware/viya4-deployment/discussions) or open a Pull Request to fix the issue. As a last resort, you can create a GitHub Issue to inform the community about the problem. 26 | 27 | If a community contributed feature is implemented as required, disabling the community feature should serve as a way to remove any impact that it has on the project. Community contributed features that affect the project when disabled should be re-worked to prevent that behavior. -------------------------------------------------------------------------------- /docs/community/community-config-vars.md: -------------------------------------------------------------------------------- 1 | # Community-Contributed Configuration Variables 2 | 3 | Community contributed configuration variables are listed in the tables below. These variables can also be specified on the terraform command line. 4 | 5 | > [!CAUTION] 6 | > Community members are responsible for maintaining these features. While project maintainers try to verify these features work as expected when merged, they cannot guarantee future releases will not break them. If you encounter issues while using these features, start a [GitHub Discussion](https://github.com/sassoftware/viya4-deployment/discussions) or open a Pull Request to fix them. As a last resort, you can create a GitHub Issue. 7 | 8 | **Instructions for use**: Replace the Community Feature TOC entry and section name with your new Community Feature name. Include information about the feature. Include any warnings and a table documenting the associated community contributed configuration variables by replacing each placeholder below with the information relevant to your community contributed feature. 9 | 10 | ## Table of Contents 11 | 12 | * [Community Feature](#community_feature) 13 | 14 | 15 | ## Community Feature 16 | 17 | Here is some information about Community Feature. 18 | 19 | Here is a warning about why it might cause issues. 20 | 21 | Here is a table with the variables you would use to configure it 22 | 23 | | Name | Description | Type | Default | Release Added | Notes | 24 | | :--- | ---: | ---: | ---: | ---: | ---: | 25 | | COMMUNITY_ENABLE_COMMUNITY_FEATURE | Enable community feature | bool | false | vMajor.Minor.Patch | | -------------------------------------------------------------------------------- /docs/user/AnsibleCloudAuthentication.md: -------------------------------------------------------------------------------- 1 | # Ansible Cloud Provider Authentication 2 | 3 | The docker container contains cloud CLIs needed for interacting with the various clouds. 4 | 5 | ## Google Cloud 6 | 7 | When using external postgres in Google Cloud, we default to using [Google Cloud SQL proxy](https://cloud.google.com/sql/docs/postgres/connect-kubernetes-engine). For security the setup is via a workload identity configuration. This requires the following vars to be set: 8 | 9 | ### V4_CFG_POSTGRES_CONNECTION_NAME 10 | 11 | Name of the SQL cluster connection, as listed in the Google Cloud console. 12 | 13 | ### V4_CFG_POSTGRES_SERVICE_ACCOUNT 14 | 15 | Name of service account in Google Cloud that has the cloudsql.admin role. This account will be mapped to a Kubernetes service account, thus granting the SQL proxy access, via workload identity, to the SQL server. 16 | 17 | ### V4_CFG_CLOUD_SERVICE_ACCOUNT_NAME 18 | 19 | Name of service account in Google Cloud that has the iam.serviceAccountAdmin role. This account will be used to setting up the sql proxy's Google service account mapping to the kubernetes service account 20 | 21 | ### V4_CFG_CLOUD_SERVICE_ACCOUNT_AUTH 22 | 23 | Path to the `` service account's keys 24 | -------------------------------------------------------------------------------- /docs/user/AnsibleUsage.md: -------------------------------------------------------------------------------- 1 | # Using Ansible 2 | 3 | ## Prereqs 4 | 5 | When using the Ansible CLI, make sure you have all the necessary tools [installed on your workstation](Dependencies.md#dependency-versions). 6 | 7 | ## Preparation 8 | 9 | ### Cloud Authentication 10 | 11 | See [ansible cloud authentication](AnsibleCloudAuthentication.md) when deploying to Google Cloud with external postgres 12 | 13 | ### Variable Definitions (ansible-vars.yaml) File 14 | 15 | Prepare your `ansible-vars.yaml` file, as described in [Customize Input Values](../../README.md#customize-input-values). The only variable that cannot be set in the ansible-vars files and instead must be set with the `-e` flag is `-e CONFIG=`. All other values can be set either in the ansible-vars.yaml file or using the `-e` extra var param in ansible. 16 | 17 | ### Initialize Ansible 18 | 19 | ```bash 20 | # install python packages 21 | pip3 install --user -r requirements.txt 22 | 23 | # install ansible collections 24 | ansible-galaxy collection install -r requirements.yaml -f 25 | ``` 26 | 27 | ### Install Docker 28 | 29 | See https://docs.docker.com/engine/install/ for steps on how to install Docker for your distro. It's a requirement to use the Orchestration tooling CLI during Viya installation. 30 | 31 | ## Running 32 | 33 | Declare the Actions and Task to be performed. 34 | 35 | ### Actions 36 | 37 | Actions are used to install or uninstall software. One must be set when running the playbook. 38 | 39 | | Name | Description | 40 | | :--- | ---: | 41 | | install | Installs the stack required for the specified tasks | 42 | | uninstall | Uninstalls the stack required for the specified tasks | 43 | 44 | ### Tasks 45 | 46 | More than one task can be run at the same time. An action can run against a single task or all tasks. 47 | 48 | | Name | Description | 49 | | :--- | :--- | 50 | | baseline | Installs cluster level tooling needed for all SAS Viya platform deployments. These may include, cert-manager, ingress-nginx, nfs-client-provisioners and more. | 51 | | viya | Deploys the SAS Viya platform | 52 | 53 | ### Examples 54 | 55 | - I have a new cluster, deployed using one of the Viya4 IAC projects, and want to install everything 56 | 57 | ```bash 58 | ansible-playbook \ 59 | -e BASE_DIR=$HOME/deployments \ 60 | -e CONFIG=$HOME/deployments/dev-cluster/dev-namespace/ansible-vars.yaml \ 61 | -e TFSTATE=$HOME/deployments/dev-cluster/terraform.tfstate \ 62 | -e JUMP_SVR_PRIVATE_KEY=$HOME/.ssh/id_rsa \ 63 | playbooks/playbook.yaml --tags "baseline,viya,install" 64 | ``` 65 | 66 | - I have a custom built cluster and want to install baseline dependencies only 67 | 68 | ```bash 69 | ansible-playbook \ 70 | -e BASE_DIR=$HOME/deployments \ 71 | -e KUBECONFIG=$HOME/deployments/.kube/config \ 72 | -e CONFIG=$HOME/deployments/dev-cluster/dev-namespace/ansible-vars.yaml \ 73 | -e JUMP_SVR_PRIVATE_KEY=$HOME/.ssh/id_rsa \ 74 | playbooks/playbook.yaml --tags "baseline,install" 75 | ``` 76 | 77 | - I want to modify a customization under site-config for an existing viya deployment and reapply the manifest. I wish to continue to use the same deployment assets rather than pull the latest copy. 78 | 79 | ```bash 80 | ansible-playbook \ 81 | -e BASE_DIR=$HOME/deployments \ 82 | -e CONFIG=$HOME/deployments/ansible-vars.yaml \ 83 | -e TFSTATE=$HOME/deployments/terraform.tfstate \ 84 | -e V4_CFG_DEPLOYMENT_ASSETS=$HOME/deployments/deployment_assets.tgz \ 85 | playbooks/playbook.yaml --tags "viya,install" 86 | ``` 87 | 88 | - I have an existing cluster with viya installed and want to install another viya instance in a different namespace 89 | 90 | ```bash 91 | ansible-playbook \ 92 | -e BASE_DIR=$HOME/deployments \ 93 | -e CONFIG=$HOME/deployments/dev-cluster/test-namespace/ansible-vars.yaml \ 94 | -e TFSTATE=$HOME/deployments/dev-cluster/terraform.tfstate \ 95 | -e JUMP_SVR_PRIVATE_KEY=$HOME/.ssh/id_rsa \ 96 | playbooks/playbook.yaml --tags "viya,install" 97 | ``` 98 | 99 | - I have a cluster with a single viya install. I want to uninstall everything 100 | 101 | ```bash 102 | ansible-playbook \ 103 | -e BASE_DIR=$HOME/deployments \ 104 | -e CONFIG=$HOME/deployments/dev-cluster/test-namespace/ansible-vars.yaml \ 105 | -e TFSTATE=$HOME/deployments/dev-cluster/terraform.tfstate \ 106 | -e JUMP_SVR_PRIVATE_KEY=$HOME/.ssh/id_rsa \ 107 | playbooks/playbook.yaml --tags "baseline,viya,uninstall" 108 | ``` 109 | 110 | ### Ansible Config 111 | 112 | In the examples above, we are running `ansible-playbook` from within the project directory. This means Ansible will automatically load the project's `ansible.cfg` file which contains configuration settings to properly run this project's playbook. If you are calling the playbook from a directory outside of this project's folder, it is important to set the following Ansible environment variable prior to running the playbook so that the configuration file gets loaded. 113 | 114 | ```bash 115 | export ANSIBLE_CONFIG=${WORKSPACE}/viya4-deployment/ansible.cfg 116 | ``` 117 | 118 | ### Monitoring and Logging 119 | 120 | To install SAS Viya Monitoring for Kubernetes, see the GitHub project https://github.com/sassoftware/viya4-monitoring-kubernetes for scripts and customization options 121 | to deploy metric monitoring, alerts and log-message aggregation for SAS Viya. 122 | -------------------------------------------------------------------------------- /docs/user/Dependencies.md: -------------------------------------------------------------------------------- 1 | # Dependency Versions 2 | 3 | If your environment requires validated support for a specific version or range of versions, please open a [Issue](https://github.com/sassoftware/viya4-deployment/issues) 4 | 5 | The following list details our dependencies and versions (~ indicates multiple possible sources): 6 | 7 | | SOURCE | NAME | VERSION | 8 | |----------------|------------------|--------------| 9 | | ~ | python | >=3.10 | 10 | | ~ | pip | 3.x | 11 | | ~ | unzip | any | 12 | | ~ | tar | any | 13 | | ~ | docker | >=25.0.3 | 14 | | ~ | git | any | 15 | | ~ | rsync | any | 16 | | ~ | kubectl | 1.30 - 1.32 | 17 | | ~ | Helm | 3.16.2 | 18 | | pip3 | ansible | 10.5.0 | 19 | | pip3 | openshift | 0.13.2 | 20 | | pip3 | kubernetes | 32.0.1 | 21 | | pip3 | dnspython | 2.7.0 | 22 | | pip3 | docker | 7.1.0 | 23 | | pip3 | urllib3 | 2.3.0 | 24 | | ansible-galaxy | community.docker | 3.13.0 | 25 | | ansible-galaxy | ansible.utils | 5.1.2 | 26 | | ansible-galaxy | kubernetes.core | 5.0.0 | 27 | 28 | If you are using a provider based kubeconfig file created by viya4-iac-gcp:4.5.0 or newer, install these dependencies: 29 | | SOURCE | NAME | VERSION | 30 | |----------------|-------------------------|-------------| 31 | | ~ | gcloud | 496.0.0 | 32 | | ~ | gcloud-gke-auth-plugin | >= 0.5.2 | 33 | 34 | Required project dependencies are generally pinned to known working or stable versions to ensure users have a smooth initial experience. In some cases it may be required to change the default version of a dependency. In such cases users are welcome to experiment with alternate versions, however compatibility may not be guaranteed. 35 | 36 | # Docker 37 | 38 | If deploying via the [Dockerfile](../../Dockerfile) overriding a dependency version can be accomplished by supplying one or more docker build arguments: 39 | 40 | | ARG | NOTE | 41 | |-----------------|----------------------------------------| 42 | | kubectl_version | the version of kubectl to use | 43 | | aws_cli_version | the version of AWS CLI to use | 44 | | gcp_cli_version | the version of Google cloud SDK to use | 45 | | helm_version | the version helm to use | 46 | 47 | As described in the [Docker Installation](./DockerUsage.md) section add additional build arguments to your docker build command: 48 | 49 | ```bash 50 | # Override kubectl version 51 | docker build \ 52 | --build-arg kubectl_version=1.31.7 \ 53 | -t viya4-deployment . 54 | ``` 55 | 56 | # Ansible 57 | 58 | If deploying via the [Ansible Commands](./AnsibleUsage.md) you can modify the dependency requirements files for python and ansible respectively: 59 | 60 | | FILE | FOR | 61 | |-------------------|---------------------------------| 62 | | requirements.txt | dependencies for python | 63 | | requirements.yaml | dependencies for ansible-galaxy | 64 | -------------------------------------------------------------------------------- /docs/user/DeploymentDirectoryStructure.md: -------------------------------------------------------------------------------- 1 | # Deployment Directory Structure 2 | 3 | This is the directory structure that the viya4-deployment project creates to store persistent files. It varies slightly from the SAS Viya Platform documentation in order to accommodate managing multiple SAS Viya Platform deployments within a single cluster. Below you will find an example of the directory structure and files that gets laid out, their use, equivalent from the SAS Viya Platform documentation if you were performing a manual deployment. 4 | 5 | ## Example Deployment Directory Structures 6 | 7 | Note: All of these examples would be created in the location that is defined by `BASE_DIR`. See [variable documentation](https://github.com/sassoftware/viya4-deployment/blob/main/docs/CONFIG-VARS.md#base). 8 | 9 | 10 | **Example 1**: Single SAS Viya Platform Deployment using the SAS Viya Platform Deployment Operator with a "cluster-wide" scope 11 | 12 | ```shell 13 | cluster 14 | ├── deployment-operator-clusterwide.yaml 15 | └── namespace 16 | ├── license 17 | │ ├── certs.zip 18 | │ └── license.jwt 19 | ├── operator-deploy-clusterwide 20 | │ ├── operator-base 21 | │ └── site-config 22 | ├── sas-bases 23 | └── site-config 24 | └── vdm 25 | ``` 26 | 27 | Tree Breakdown 28 | 29 | * `cluster`: Folder created per cluster that you are deploying to. It can house multiple `namespace` folders which would indicate multiple SAS Viya Platform deployments were performed within a single cluster. 30 | * `namespace`: Folder created per namespace within the cluster where you are performing the SAS Viya Platform deployment in. In our case we treat it similarly to the `$deploy` directory from the [SAS Viya Platform Administration documentation](https://documentation.sas.com/?cdcId=sasadmincdc&cdcVersion=default&docsetId=dplyml0phy0dkr&docsetTarget=p1goxvcgpb7jxhn1n85ki73mdxc8.htm#p03uez7j2g8f0vn1m4xch4izmum0) and store our `sas-bases` and `site-config` files in there. 31 | * `license`: contains the .jwt file that licenses your software and the *-certs.zip file that contains the entitlement and CA certificates 32 | * `operator-deploy-$SCOPE`: Contains the operator kustomization.yaml file, used only for configuring and deploying the SAS Viya Platform Deployment Operator. The folder is appended with either "clusterwide" or "namespace" depending on the scope you chose for it using the `V4_DEPLOYMENT_OPERATOR_SCOPE` variable. This folder will not present if you set `V4_DEPLOYMENT_OPERATOR_ENABLED` to "false" and opt to use the [sas-orchestration command](https://documentation.sas.com/?cdcId=itopscdc&cdcVersion=default&docsetId=itopscon&docsetTarget=p0839p972nrx25n1dq264egtgrcq.htm) 33 | * `sas-bases`: contains the files that SAS provides to deploy your software. Extracted from the deployment assets. 34 | * `site-config`: Location for all customizations. This includes user provided customizations, [see documentation](https://github.com/sassoftware/viya4-deployment#sas-viya-customizations). 35 | * `vdm`: Contains the SAS Viya platform customizations files that are managed by viya4-deployment. These particular files are configured via exposed variables that are documented within [CONFIG-VARS.md](docs/CONFIG-VARS.md) and do not need to be manually placed under `/site-config`. 36 | * `deployment-operator-clusterwide.yaml`: File created when the SAS Viya Platform Deployment Operator is being used in the "clusterwide" mode. Contains information about the active "clusterwide" SAS Viya Platform Deployment Operator, useful when managing multiple SAS Viya platform deployments in a single cluster. This file will not present if you set `V4_DEPLOYMENT_OPERATOR_SCOPE` is set to "namespace" or if opt to use the [sas-orchestration command](https://documentation.sas.com/?cdcId=itopscdc&cdcVersion=default&docsetId=itopscon&docsetTarget=p0839p972nrx25n1dq264egtgrcq.htm) 37 | 38 | 39 | **Example 2**: Single SAS Viya Platform Deployment using the "sas-orchestration" command 40 | 41 | ```shell 42 | cluster 43 | └── namespace 44 | ├── license 45 | │ ├── certs.zip 46 | │ └── license.jwt 47 | ├── sas-bases 48 | └── site-config 49 | └── vdm 50 | ``` 51 | 52 | Note: you will see that `operator-deploy-$SCOPE` directory nor the `deployment-operator-clusterwide.yaml` file is present since the SAS Viya Platform Deployment Operator is not in use. See above for tree breakdown for applicable directories. 53 | 54 | **Example 3**: Multiple SAS Viya Platform Deployments in a single cluster using the SAS Viya Platform Deployment Operator with a "namespace" scope 55 | 56 | ```shell 57 | cluster 58 | ├── namespace1 59 | │ ├── license 60 | │ │ ├── certs.zip 61 | │ │ └── license.jwt 62 | │ ├── operator-deploy-namespace 63 | │ │ ├── operator-base 64 | │ │ └── site-config 65 | │ ├── sas-bases 66 | │ └── site-config 67 | │ └── vdm 68 | └── namespace2 69 | ├── license 70 | │ ├── certs.zip 71 | │ └── license.jwt 72 | ├── operator-deploy-namespace 73 | │ ├── operator-base 74 | │ └── site-config 75 | ├── sas-bases 76 | └── site-config 77 | └── vdm 78 | ``` 79 | 80 | Note: you will see that `deployment-operator-clusterwide.yaml` is not present in this example since `V4_DEPLOYMENT_OPERATOR_SCOPE` is set to "namespace". See above for tree breakdown for applicable directories. -------------------------------------------------------------------------------- /docs/user/DockerVolumeMounts.md: -------------------------------------------------------------------------------- 1 | # Docker Volume Mapping 2 | 3 | Ansible vars to docker volume mounts mappings. For full listing of config vars see [CONFIG-VARS.md](../CONFIG-VARS.md) 4 | 5 | ## Base 6 | 7 | | Ansible Var | Docker Mount | 8 | | :--- | ---: | 9 | | BASE_DIR | `--volume :/data `| 10 | | KUBECONFIG | `--volume :/config/kubeconfig `| 11 | | V4_CFG_SITEDEFAULT | `--volume :/config/v4_cfg_sitedefault `| 12 | | V4_CFG_SSSD | `--volume :/config/v4_cfg_sssd `| 13 | 14 | ## Jump Server 15 | 16 | | Ansible Var | Docker Mount | 17 | | :--- | ---: | 18 | | JUMP_SVR_PRIVATE_KEY | `--volume :/config/jump_svr_private_key `| 19 | 20 | ## Order 21 | 22 | | Ansible Var | Docker Mount | 23 | | :--- | ---: | 24 | | V4_CFG_DEPLOYMENT_ASSETS | `--volume :/config/v4_cfg_deployment_assets `| 25 | | V4_CFG_LICENSE | `--volume :/config/v4_cfg_license `| 26 | | V4_CFG_CERTS | `--volume :/config/v4_cfg_certs `| 27 | 28 | ## TLS 29 | 30 | | Ansible Var | Docker Mount | 31 | | :--- | ---: | 32 | | V4_CFG_TLS_CERT | `--volume :/config/v4_cfg_tls_cert `| 33 | | V4_CFG_TLS_KEY | `--volume :/config/v4_cfg_tls_key `| 34 | | V4_CFG_TLS_TRUSTED_CA_CERTS | `--volume :/config/v4_cfg_tls_trusted_ca_certs `| 35 | 36 | ## Cloud Info 37 | 38 | | Ansible Var | Docker Mount | 39 | | :--- | ---: | 40 | | V4_CFG_CLOUD_SERVICE_ACCOUNT_AUTH | `--volume :/config/v4_cfg_cloud_service_account_auth `| 41 | -------------------------------------------------------------------------------- /docs/user/Kubeconfig.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Configuration File Types 2 | 3 | ## Overview 4 | 5 | ### Notes - viya4-deployment:6.6.0 6 | 7 | The release of kubectl v1.26 is dropping support for built-in provider-specific code in their project for authentication and instead opting for a plugin-based strategy. A quote from the [Google blog](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke) provides an explanation for this change: 8 | 9 | >To ensure the separation between the open source version of Kubernetes and those versions that are customized by services providers like Google, the open source community is requiring that all provider-specific code that currently exists in the OSS code base be removed starting with v1.26. 10 | 11 | ### Usage with provider based kubeconfig files from viya4-iac-gcp:4.5.0 12 | 13 | Two types of Kubernetes configuration files can be created with the [viya4-iac-gcp](https://github.com/sassoftware/viya4-iac-gcp) project: 14 | 15 | - Provider Based 16 | - Kubernetes Service Account and Cluster Role Binding 17 | 18 | Starting with viya4-iac-gcp:4.5.0, the provider based kubernetes configuration file format will change to support use of the `gke-gcloud-auth-plugin`. The `gke-gcloud-auth-plugin` binary is required to access any GKE clusters when using kubectl 1.26+ with a "provider based" kubernetes configuration file. When used with the viya4-deployment project, the "service account and cluster role binding" kubernetes configuration file variant remains the same and does not require either `gcloud` or the `gke-gcloud-auth-plugin` binary to communicate with the cluster. 19 | 20 | The viya4-deployment Dockerfile includes steps to ensure that the `gke-gcloud-auth-plugin` is installed and enabled for use with provider based kubeconfig files. If you opt to [use the Ansible CLI](./AnsibleUsage.md) with this project instead of a Docker container produced with the included Dockerfile, and you are using a provider based kubeconfig file, you will need to take steps to install both `gcloud` and the `gke-gcloud-auth-plugin` on your machine. Google has provided step-by-step instructions in a blog post to aid users with this transition. See [Google's Authentication Blog post](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke). 21 | 22 | See the [viya4-iac-gcp Kubeconfig document](https://github.com/sassoftware/viya4-iac-gcp/blob/main/docs/user/Kubeconfig.md) for more details on creating both types of GKE Kubernetes Configuration files. 23 | 24 | ### Examples 25 | 26 | Using the viya4-deployment project with a viya4-iac-gcp "provider based" kubeconfig file requires providing values for the V4_CFG_CLOUD_SERVICE_ACCOUNT_NAME and a V4_CLOUD_SERVICE_ACCOUNT_AUTH file. Refer to the section below for examples of how to express those two values with either the docker container or ansible CLI usage patterns. 27 | 28 | - I have opted to use this project via a Docker container produced with the provided Dockerfile. I have a provider based Kubernetes configuration file and I want to baseline and deploy Viya only. 29 | 30 | ```bash 31 | docker run --rm --group-add root --user "$(id -u):$(id -g)" --volume "$HOME"/deployments:/data \ 32 | --volume $HOME/deployments/dev-cluster/dev-namespace/ansible-vars-iac-gcp.yaml:/config/config \ 33 | --volume $HOME/terraform.tfstate:/config/tfstate \ 34 | --volume $HOME/.ssh/id_rsa:/config/jump_svr_private_key \ 35 | --volume $HOME/public/prefix-gke-kubeconfig.conf:/config/kubeconfig \ 36 | --volume $HOME/credentials/.gcp-service-account.json:/config/v4_cfg_cloud_service_account_auth \ 37 | viya4-deployment --tags "baseline,viya,install" -v -e V4_CFG_CLOUD_SERVICE_ACCOUNT_NAME=proj-terraform@project.iam.gserviceaccount.com 38 | ``` 39 | 40 | - I have opted to use this project with the ansible CLI and have followed the linked steps above to install both `gcloud` and the `gke-gcloud-auth-plugin`. I have a provider based Kubernetes configuration file and I want to baseline and deploy Viya only. 41 | 42 | ```bash 43 | ansible-playbook \ 44 | -e V4M_VERSION=stable -e BASE_DIR=$HOME/deployments \ 45 | -e KUBECONFIG=$HOME/deployments/dev-cluster/dev-namespace/prefix-gke-kubeconfig.conf \ 46 | -e CONFIG=$HOME/deployments/dev-cluster/dev-namespace/ansible-vars-iac-gcp.yaml \ 47 | -e TFSTATE=$HOME/deployments/dev-cluster/dev-namespace/terraform.tfstate \ 48 | -e JUMP_SVR_PRIVATE_KEY=$HOME/.ssh/id_rsa \ 49 | -e V4_CFG_CLOUD_SERVICE_ACCOUNT_NAME=proj-terraform@project.iam.gserviceaccount.com \ 50 | -e V4_CFG_CLOUD_SERVICE_ACCOUNT_AUTH=$HOME/creds/.gcp-service-account.json \ 51 | playbooks/playbook.yaml --tags "baseline,viya,install" -v 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/user/ThirdPartyComponents.md: -------------------------------------------------------------------------------- 1 | ### Third-Party Components 2 | The following is a list of the third-party components currently in full support/used by the Viya4 DaC. You can also find the chart repo URLs referenced in the repo [README](../README.md). 3 | 4 | | Component | Chart Name | Chart Source URL | Container Registry | Purpose | Cloud Provider Support | 5 | |------------------|-------------------|----------------------------------------------------------------------------------------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------|----------------------------------| 6 | | ingress-nginx | ingress-nginx | https://github.com/kubernetes/ingress-nginx/tree/main/charts/ingress-nginx | quay.io | Provides ingress controller for Kubernetes. | AWS, Azure, GCP, generic K8s | 7 | | cert-manager | cert-manager | https://github.com/cert-manager/cert-manager/tree/master/deploy/charts/cert-manager | quay.io | Manages TLS certificates in Kubernetes. | AWS, Azure, GCP, generic K8s | 8 | | metrics-server | metrics-server | https://github.com/kubernetes-sigs/metrics-server/tree/master/charts/metrics-server | registry.k8s.io | Collects resource metrics from K8s nodes and pods. | AWS only | 9 | | csi-driver-nfs | csi-driver-nfs | https://github.com/kubernetes-csi/csi-driver-nfs/tree/master/charts | registry.k8s.io, gcr.io | Provides NFS storage provisioning for Kubernetes (supports AWS EFS, GCP Filestore, Azure Files, NFS). | AWS, Azure, GCP, generic NFS | 10 | | ebs-csi-driver | aws-ebs-csi-driver| https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/charts/aws-ebs-csi-driver | public.ecr.aws | Provides dynamic provisioning of AWS EBS volumes for persistent storage in Kubernetes. | AWS only | 11 | 12 | **Notes:** 13 | - These are the only third-party components installed by default by the DaC. 14 | - All components are installed and managed via Ansible playbooks and Helm charts. 15 | - Chart versions are managed in the Ansible variables and can be overridden by the user if needed. 16 | - All components are compatible with AWS, Azure, and GCP unless otherwise noted. `metrics-server` and `ebs-csi-driver` are for AWS only. 17 | - For more details on how to add or update these components, see the main playbook in `playbooks/playbook.yaml` and the role documentation in the `roles/` directory. -------------------------------------------------------------------------------- /docs/user/TrustedCACerts.md: -------------------------------------------------------------------------------- 1 | # Using Trusted CA Certs 2 | 3 | ## How to obtain an AWS certificate bundle 4 | 5 | To obtain a certificate bundle that contains both the intermediate and root certificates for all AWS Regions, you can download the PEM file from https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html 6 | 7 | ## How to Obtain an Open Source Kubernetes Certificate Bundle 8 | 9 | If you are performing a SAS Viya platform deployment into a cluster in open source Kubernetes that was created with the [viya4-iac-k8s](https://github.com/sassoftware/viya4-iac-k8s) project, and if you want to obtain the certificates for the external PostgreSQL database, follow the steps in the "Notes" section in the [documentation here](https://github.com/sassoftware/viya4-iac-k8s/blob/main/docs/CONFIG-VARS.md#postgresql-server). You will have the option to either use the system default certificates, in which case they will be copied to your workspace for use, or you can provide your own generated certificates. -------------------------------------------------------------------------------- /examples/ansible-vars-iac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ## Cluster 3 | NAMESPACE: 4 | 5 | ## MISC 6 | DEPLOY: true # Set to false to stop at generating the manifest 7 | LOADBALANCER_SOURCE_RANGES: [] 8 | ## Storage 9 | V4_CFG_MANAGE_STORAGE: true 10 | 11 | ## SAS API Access 12 | V4_CFG_SAS_API_KEY: 13 | V4_CFG_SAS_API_SECRET: 14 | V4_CFG_ORDER_NUMBER: 15 | V4_CFG_CADENCE_NAME: # [lts|stable] 16 | V4_CFG_CADENCE_VERSION: 17 | 18 | ## CR Access 19 | V4_CFG_CR_USER: 20 | V4_CFG_CR_PASSWORD: 21 | 22 | ## Ingress 23 | V4_CFG_INGRESS_TYPE: ingress 24 | V4_CFG_INGRESS_FQDN: 25 | V4_CFG_TLS_MODE: full-stack # [full-stack|front-door|ingress-only|disabled] 26 | 27 | ## Postgres 28 | 29 | ## LDAP 30 | V4_CFG_EMBEDDED_LDAP_ENABLE: true 31 | 32 | ## Consul UI 33 | V4_CFG_CONSUL_ENABLE_LOADBALANCER: false 34 | 35 | ## SAS/CONNECT 36 | V4_CFG_CONNECT_ENABLE_LOADBALANCER: false 37 | 38 | ## Viya Start and Stop Schedule 39 | ## uncomment and update the values below with CronJob schedule expressions if you would 40 | ## like to start and stop your Viya Deployment on a schedule 41 | # V4_CFG_VIYA_START_SCHEDULE: "0 7 * * 1-5" 42 | # V4_CFG_VIYA_STOP_SCHEDULE: "0 19 * * 1-5" 43 | -------------------------------------------------------------------------------- /examples/ansible-vars.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ## Cluster 3 | PROVIDER: 4 | CLUSTER_NAME: 5 | NAMESPACE: 6 | 7 | ## MISC 8 | DEPLOY: true # Set to false to stop at generating the manifest 9 | LOADBALANCER_SOURCE_RANGES: [/32] 10 | 11 | ## Jump 12 | JUMP_SVR_HOST: 13 | JUMP_SVR_USER: 14 | 15 | ## RWX Filestore 16 | V4_CFG_RWX_FILESTORE_ENDPOINT: 17 | V4_CFG_RWX_FILESTORE_PATH: 18 | 19 | ## Storage 20 | V4_CFG_MANAGE_STORAGE: true 21 | 22 | ## SAS API Access 23 | V4_CFG_SAS_API_KEY: 24 | V4_CFG_SAS_API_SECRET: 25 | V4_CFG_ORDER_NUMBER: 26 | V4_CFG_CADENCE_NAME: # [lts|stable] 27 | V4_CFG_CADENCE_VERSION: 28 | 29 | ## CR Access 30 | V4_CFG_CR_USER: 31 | V4_CFG_CR_PASSWORD: 32 | 33 | ## Ingress 34 | V4_CFG_INGRESS_TYPE: ingress 35 | V4_CFG_INGRESS_FQDN: 36 | V4_CFG_TLS_MODE: full-stack # [full-stack|front-door|ingress-only|disabled] 37 | 38 | ## Postgres 39 | V4_CFG_POSTGRES_SERVERS: 40 | default: 41 | internal: false 42 | admin: 43 | password: 44 | fqdn: 45 | ssl_enforcement_enabled: true 46 | database: 47 | 48 | ## LDAP 49 | V4_CFG_EMBEDDED_LDAP_ENABLE: true 50 | 51 | ## Consul UI 52 | V4_CFG_CONSUL_ENABLE_LOADBALANCER: false 53 | 54 | ## SAS/CONNECT 55 | V4_CFG_CONNECT_ENABLE_LOADBALANCER: false 56 | 57 | ## Monitoring and Logging 58 | ## uncomment and update the below values when deploying the viya4-monitoring-kubernetes stack 59 | # V4M_BASE_DOMAIN: 60 | 61 | ## Viya Start and Stop Schedule 62 | ## uncomment and update the values below with CronJob schedule expressions if you would 63 | ## like to start and stop your Viya Deployment on a schedule 64 | # V4_CFG_VIYA_START_SCHEDULE: "0 7 * * 1-5" 65 | # V4_CFG_VIYA_STOP_SCHEDULE: "0 19 * * 1-5" 66 | -------------------------------------------------------------------------------- /examples/multi-tenancy/ansible-vars-multi-tenancy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ## Cluster 3 | PROVIDER: 4 | CLUSTER_NAME: 5 | NAMESPACE: 6 | 7 | ## MISC 8 | DEPLOY: true # Set to false to stop at generating the manifest 9 | LOADBALANCER_SOURCE_RANGES: [/32] 10 | 11 | ## Storage 12 | V4_CFG_MANAGE_STORAGE: true 13 | 14 | ## SAS API Access 15 | V4_CFG_SAS_API_KEY: 16 | V4_CFG_SAS_API_SECRET: 17 | V4_CFG_ORDER_NUMBER: 18 | V4_CFG_CADENCE_NAME: # [lts|stable] 19 | V4_CFG_CADENCE_VERSION: 20 | 21 | ## CR Access 22 | V4_CFG_CR_USER: 23 | V4_CFG_CR_PASSWORD: 24 | 25 | ## Ingress 26 | V4_CFG_INGRESS_TYPE: ingress 27 | V4_CFG_INGRESS_FQDN: 28 | V4_CFG_TLS_MODE: full-stack # [full-stack|front-door|ingress-only|disabled] 29 | 30 | ## Internal Postgres -- remove this section if using external Postgres 31 | V4_CFG_POSTGRES_SERVERS: 32 | default: 33 | internal: false 34 | admin: 35 | password: 36 | fqdn: 37 | ssl_enforcement_enabled: true 38 | database: 39 | 40 | ## LDAP 41 | V4_CFG_EMBEDDED_LDAP_ENABLE: true 42 | 43 | ## Multi-Tenant 44 | V4MT_ENABLE: true 45 | # SAS Viya supports two modes of data isolation (schemaPerApplicationTenant and databasePerTenant) for tenant data. 46 | # Set V4MT_MODE to either schema or database 47 | V4MT_MODE: 48 | V4MT_TENANT_IDS: # For single tenant ID: "acme" or for multiple tenant IDs: "acme, cyberdyne, intech" 49 | 50 | # Optional: Either set password for sasprovider, common to all tenants or set unique passwords for each tenants. 51 | # V4MT_PROVIDER_PASSWORD: "" 52 | 53 | # Or 54 | 55 | # V4MT_PROVIDER_PASSWORD_ACME: "" 56 | # V4MT_PROVIDER_PASSWORD_CYBERDYNE: "" 57 | # V4MT_PROVIDER_PASSWORD_INTECH: "" 58 | -------------------------------------------------------------------------------- /examples/openldap/openldap-modify-users.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: openldap-users 6 | patch: |- 7 | - op: replace 8 | path: /data/LDAP_USERS_CONF 9 | value: |- 10 | dn: uid=viya_admin,ou=people,dc=example,dc=com 11 | changetype: add 12 | objectClass: inetOrgPerson 13 | objectclass: extensibleObject 14 | uid: viya_admin 15 | uidNumber: 2001 16 | gidNumber: 2000 17 | cn: administrator 18 | sn: Admin 19 | homeDirectory: /home/viya_admin 20 | mail: viya_admin@example.com 21 | distinguishedName: uid=viya_admin,ou=people,dc=example,dc=com 22 | displayName: Viya Administrator 23 | userPassword: Password123 24 | 25 | dn: uid=basic_user1,ou=people,dc=example,dc=com 26 | changetype: add 27 | objectClass: inetOrgPerson 28 | objectclass: extensibleObject 29 | uid: basic_user1 30 | uidNumber: 7001 31 | gidNumber: 1000 32 | cn: basic_user1 33 | sn: BasicUser 34 | distinguishedName: uid=basic_user1,ou=people,dc=example,dc=com 35 | displayName: Basic User 1 36 | userPassword: mySuperSecretPassword 37 | homeDirectory: /home/basic_user1 38 | mail: basic_user1@example.com 39 | 40 | dn: cn=users,ou=groups,dc=example,dc=com 41 | changetype: add 42 | objectclass: groupofUniqueNames 43 | objectclass: extensibleObject 44 | gidNumber: 1000 45 | distinguishedName: cn=group1,ou=groups,dc=example,dc=com 46 | uniqueMember:uid=basic_user1,ou=people,dc=example,dc=com 47 | 48 | dn: cn=admins,ou=groups,dc=example,dc=com 49 | changetype: add 50 | objectclass: groupofUniqueNames 51 | objectclass: extensibleObject 52 | gidNumber: 2000 53 | distinguishedName: cn=admins,ou=groups,dc=example,dc=com 54 | uniqueMember:uid=viya_admin,ou=people,dc=example,dc=com 55 | target: 56 | kind: ConfigMap 57 | name: openldap-bootstrap-config 58 | version: v1 59 | -------------------------------------------------------------------------------- /examples/sitedefault.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | cacerts: 3 | config: 4 | application: 5 | sas.identities.providers.ldap.connection: 6 | host: ldap-svc 7 | password: Password123 8 | port: 389 9 | url: ldap://${sas.identities.providers.ldap.connection.host}:${sas.identities.providers.ldap.connection.port} 10 | userDN: cn=admin,dc=example,dc=com 11 | sas.identities.providers.ldap.group: 12 | baseDN: ou=groups,dc=example,dc=com 13 | accountId: cn 14 | member: uniqueMember 15 | memberOf: memberOf 16 | objectClass: groupOfUniqueNames 17 | objectFilter: (objectClass=groupOfUniqueNames) 18 | searchFilter: cn={0} 19 | sas.identities.providers.ldap.user: 20 | baseDN: ou=people,dc=example,dc=com 21 | accountId: uid 22 | memberOf: memberOf 23 | objectClass: inetOrgPerson 24 | objectFilter: (objectClass=inetOrgPerson) 25 | searchFilter: uid={0} 26 | sas.logon.initial.password: Password123 27 | config/identities/sas.identities/administrator: viya_admin 28 | -------------------------------------------------------------------------------- /examples/sssd.conf: -------------------------------------------------------------------------------- 1 | [sssd] 2 | #debug_level = 9 3 | config_file_version = 2 4 | services = nss,pam 5 | sbus_timeout = 30 6 | domains = example.com 7 | 8 | [pam] 9 | #debug_level = 9 10 | 11 | [domain/example.com] 12 | #debug_level = 9 13 | enumerate = true 14 | cache_credentials = true 15 | ignore_group_members = true 16 | id_provider = ldap 17 | auth_provider = ldap 18 | chpass_provider = ldap 19 | ldap_uri = ldap://ldap-svc:389 20 | ldap_schema = rfc2307bis 21 | ldap_user_object_class = inetOrgPerson 22 | ldap_user_member_of = memberof 23 | ldap_referrals = false 24 | ldap_search_base = dc=example,dc=com 25 | ldap_group_search_base = ou=groups,dc=example,dc=com 26 | ldap_user_search_base = ou=people,dc=example,dc=com 27 | ldap_default_bind_dn = cn=admin,dc=example,dc=com 28 | ldap_default_authtok = admin 29 | ldap_auth_disable_tls_never_use_in_production = true 30 | 31 | [nss] 32 | filter_users = root 33 | filter_groups = root 34 | 35 | # override the user home directory that is provided by the LDAP password entry 36 | override_homedir=/mnt/homes/%u 37 | 38 | # override the user shell that is provided by the LDAP password entry 39 | override_shell=/bin/bash 40 | 41 | -------------------------------------------------------------------------------- /linting-configs/.ansible-lint: -------------------------------------------------------------------------------- 1 | --- 2 | # .ansible-lint 3 | 4 | profile: moderate 5 | verbosity: 1 6 | strict: true 7 | 8 | # Enforce variable names to follow pattern below, in addition to Ansible own 9 | # requirements, like avoiding python identifiers. To disable add `var-naming` 10 | # to skip_list. 11 | var_naming_pattern: ^[a-zA-Z0-9_]*$ 12 | 13 | use_default_rules: true 14 | 15 | # Ansible-lint is able to recognize and load skip rules stored inside 16 | # `.ansible-lint-ignore` (or `.config/ansible-lint-ignore.txt`) files. 17 | # To skip a rule just enter filename and tag, like "playbook.yml package-latest" 18 | # on a new line. 19 | skip_list: 20 | - role-name # DAC roles names contain dashes, can be ignored 21 | - yaml[line-length] # it's easier to understand/debug the underlying command when it's not broken up 22 | - name[template] # task name uses Jina template, this can be ignored 23 | - var-naming 24 | 25 | # Ansible-lint does not automatically load rules that have the 'opt-in' tag. 26 | # You must enable opt-in rules by listing each rule 'id' below. 27 | enable_list: 28 | - args 29 | - empty-string-compare 30 | - no-log-password 31 | - no-same-owner 32 | - yaml 33 | 34 | # exclude_paths included in this file are parsed relative to this file's location 35 | # and not relative to the CWD of execution. CLI arguments passed to the --exclude 36 | # option are parsed relative to the CWD of execution. 37 | exclude_paths: 38 | - .git/ 39 | - .gitignore 40 | - .cache/ 41 | - roles/istio 42 | - roles/vdm/tasks/deploy.yaml # TODO schema[tasks] error for a docker 'Deploy BLT - Deploy SAS Viya' task 43 | - .github/workflows # non ansible files 44 | 45 | # Offline mode disables installation of requirements.yml and schema refreshing 46 | offline: false 47 | 48 | # Define required Ansible's variables to satisfy syntax check 49 | extra_vars: 50 | deployment_type: vsphere 51 | 52 | warn_list: 53 | - experimental 54 | - no-changed-when 55 | -------------------------------------------------------------------------------- /linting-configs/.hadolint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ignored: 3 | - DL3008 # Specify version with apt-get install -y = : https://github.com/hadolint/hadolint/wiki/DL3008 4 | - DL3018 # https://github.com/hadolint/hadolint/wiki/DL3018 5 | - DL3042 # https://github.com/hadolint/hadolint/wiki/DL3042 # Using pip cache purge to reduce image size instead 6 | - DL4006 # Experiments using -o pipefail option wth bash caused significant slowdown during image build 7 | -------------------------------------------------------------------------------- /linting-configs/.shellcheckrc: -------------------------------------------------------------------------------- 1 | # Review 'man shellcheck' section 'RC FILES' for instructions on adding directives. 2 | 3 | # Allow using `which` since it gives full paths and is common enough 4 | # https://github.com/koalaman/shellcheck/wiki/SC2230 5 | disable=SC2145,SC2230,SC2068 6 | -------------------------------------------------------------------------------- /playbooks/README.md: -------------------------------------------------------------------------------- 1 | ### Viya4 DaC Playbook Overview 2 | 1. **Create Global Temporary Directory** 3 | 4 | - Task: `Global tmp dir` 5 | - Action: Creates a temporary directory for use during the playbook run. 6 | - Tags: `install`, `uninstall`, `update`, `onboard`, `cas-onboard`, `offboard` 7 | - **Networking Considerations:** No anticipated network impact. 8 | 2. **Run Task Validations from Common Role** 9 | 10 | - Task: `Common role - task validations` 11 | - Action: Includes `common` role’s `task-validations` tasks. 12 | - Tags: `always` (runs every time) 13 | - **Networking Considerations:** No anticipated network impact. 14 | 3. **Include Main Tasks from Common Role** 15 | 16 | - Task: `Common role` 17 | - Action: Includes the main tasks from the `common` role, making its variables public. 18 | - Tags: `install`, `uninstall`, `update`, `onboard`, `cas-onboard`, `offboard` 19 | - **Networking Considerations:** No anticipated network impact. 20 | 4. **Optionally Include Jump-Server Role** 21 | 22 | - Task: `jump-server role` 23 | - Action: Includes the `jump-server` role. 24 | - Condition: Runs only if all of these are defined: `JUMP_SVR_HOST`, `JUMP_SVR_USER`, `JUMP_SVR_PRIVATE_KEY`, `V4_CFG_MANAGE_STORAGE` and if `V4_CFG_MANAGE_STORAGE` is `true`. 25 | - Tags: `viya` 26 | - **Networking Considerations:** May require SSH access to the jump server and NFS server. See [NetworkingConsiderations.md](../docs/user/NetworkingConsiderations.md) 27 | 5. **Optionally Include Baseline Role for Install** 28 | 29 | - Task: `baseline role install` 30 | - Action: Includes the `baseline` role for install actions. 31 | - Condition: Runs only if both `'baseline'` and `'install'` are in `ansible_run_tags`. 32 | - Tags: `baseline` 33 | - **Networking Considerations:** Deploys core components (ingress-nginx, cert-manager, metrics-server, csi-driver-nfs, ebs-csi-driver, etc.) that impact cluster networking, ingress, and storage. See [NetworkingConsiderations.md](../docs/user/NetworkingConsiderations.md) 34 | 6. **Optionally Include Multi-Tenancy Role** 35 | 36 | - Task: `Multi-tenancy role` 37 | - Action: Includes the `multi-tenancy` role. 38 | - Condition: Runs only if `V4MT_ENABLE` is defined. 39 | - Tags: `multi-tenancy` 40 | - **Networking Considerations:** May create namespaces and network policies. See [NetworkingConsiderations.md](../docs/user/NetworkingConsiderations.md) 41 | 7. **Include VDM Role** 42 | 43 | - Task: `vdm role` 44 | - Action: Includes the `vdm` role. 45 | - Tags: `viya`, `multi-tenancy` 46 | - **Networking Considerations:** May create services and resources that affect networking within the cluster. 47 | 8. **Optionally Include Baseline Role for Uninstall** 48 | 49 | - Task: `baseline role uninstall` 50 | - Action: Includes the `baseline` role for uninstall actions. 51 | - Condition: Runs only if both `'baseline'` and `'uninstall'` are in `ansible_run_tags`. 52 | - Tags: `baseline` 53 | - **Networking Considerations:** Removes core components and may affect networking and storage resources. See [NetworkingConsiderations.md](../docs/user/NetworkingConsiderations.md) 54 | 9. **Delete Temporary Directory** 55 | 56 | - Task: `Delete tmpdir` 57 | - Action: Removes the temporary directory created at the start. 58 | - Tags: `install`, `uninstall`, `update` 59 | - **Networking Considerations:** No anticipated network impact. 60 | **Summary:** 61 | - Tasks are executed in the order listed above. 62 | - Some tasks/roles are conditionally included based on variables or tags. 63 | - The playbook is designed to be flexible for different deployment scenarios by using tags and conditions. 64 | - For a detailed summary of networking considerations, see [NetworkingConsiderations.md](../docs/user/NetworkingConsiderations.md) 65 | -------------------------------------------------------------------------------- /playbooks/playbook.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # Define an Ansible playbook for deploying Viya 6 | - name: Play for deploying Viya # Name of the play 7 | hosts: localhost # Run all tasks on the local machine 8 | tasks: # List of tasks to execute 9 | 10 | # Create a global temporary directory for use during the playbook run 11 | - name: Global tmp dir 12 | tempfile: 13 | state: directory # Ensure a directory is created 14 | register: tmpdir # Save the result to 'tmpdir' variable 15 | tags: # Tags for selective task execution 16 | - install 17 | - uninstall 18 | - update 19 | - onboard 20 | - cas-onboard 21 | - offboard 22 | 23 | # Run task validations from the 'common' role 24 | - name: Common role - task validations 25 | include_role: 26 | name: common # Include the 'common' role 27 | tasks_from: task-validations # Use the 'task-validations' task file 28 | tags: 29 | - always # Always run this task 30 | 31 | # Include the main tasks from the 'common' role 32 | - name: Common role 33 | include_role: 34 | name: common 35 | public: true # Make role variables public 36 | tags: 37 | - install 38 | - uninstall 39 | - update 40 | - onboard 41 | - cas-onboard 42 | - offboard 43 | 44 | # Conditionally include the 'jump-server' role if all required vars are defined and storage is managed 45 | - name: jump-server role # noqa: name[casing] 46 | include_role: 47 | name: jump-server 48 | when: 49 | - JUMP_SVR_HOST is defined 50 | - JUMP_SVR_USER is defined 51 | - JUMP_SVR_PRIVATE_KEY is defined 52 | - V4_CFG_MANAGE_STORAGE is defined 53 | - V4_CFG_MANAGE_STORAGE|bool 54 | tags: 55 | - viya 56 | 57 | # Conditionally include the 'baseline' role for install if tags match 58 | - name: baseline role install # noqa: name[casing] 59 | include_role: 60 | name: baseline 61 | when: ('baseline' in ansible_run_tags) and ('install' in ansible_run_tags) 62 | tags: 63 | - baseline 64 | 65 | # Conditionally include the 'multi-tenancy' role if multi-tenancy is enabled 66 | - name: Multi-tenancy role 67 | include_role: 68 | name: multi-tenancy 69 | when: V4MT_ENABLE is defined 70 | tags: 71 | - multi-tenancy 72 | 73 | # Include the 'vdm' role for viya and multi-tenancy tags 74 | - name: vdm role # noqa: name[casing] 75 | include_role: 76 | name: vdm 77 | tags: 78 | - viya 79 | - multi-tenancy 80 | 81 | # Conditionally include the 'baseline' role for uninstall if tags match 82 | - name: baseline role uninstall # noqa: name[casing] 83 | include_role: 84 | name: baseline 85 | when: ('baseline' in ansible_run_tags) and ('uninstall' in ansible_run_tags) 86 | tags: 87 | - baseline 88 | 89 | # Clean up: delete the temporary directory created at the start 90 | - name: Delete tmpdir 91 | file: 92 | path: "{{ tmpdir.path }}" # Path to the temp directory 93 | state: absent # Ensure it is removed 94 | tags: 95 | - install 96 | - uninstall 97 | - update 98 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ansible~=10.5.0 # 9.6.0 # 9.2.0 # 9.1.0 # 8.6.0 # 2.10.7 2 | openshift==0.13.2 # 0.13.1 # 0.12.0 3 | kubernetes~=32.0.1 # 27.2.0 # 26.1.0 # 12.0.1 4 | dnspython==2.7.0 # 2.6.1 # 2.3.0 # 2.1.0 5 | docker==7.1.0 # 7.0.0 # 5.0.3 6 | urllib3~=2.3.0 # 1.26.18 7 | wheel>=0.44.0 # 0.38.1 8 | setuptools>=75.1.0 # 65.5.1 9 | -------------------------------------------------------------------------------- /requirements.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: 3 | - name: ansible.utils 4 | version: 5.1.2 # 4.1.0 # 3.1.0 # 2.3.0 5 | - name: community.docker 6 | version: 3.13.0 # 3.10.3 # 3.8.0 # 2.7.8 7 | - name: kubernetes.core 8 | version: 5.0.0 # 3.0.0 # 2.3.2 9 | -------------------------------------------------------------------------------- /roles/baseline/tasks/cert-manager.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the cert-manager setup tasks for the baseline role. 6 | # Chart Repo URL: https://charts.jetstack.io/ 7 | # Container registry: quay.io 8 | # Chart Source: https://github.com/cert-manager/cert-manager/tree/master/deploy/charts/cert-manager 9 | # Purpose: Installs and manages cert-manager for TLS certificate management in Kubernetes. 10 | 11 | # Deploy the cert-manager controller using Helm 12 | - name: Deploy cert-manager 13 | kubernetes.core.helm: 14 | name: "{{ CERT_MANAGER_NAME }}" # Name of the Helm release 15 | namespace: "{{ CERT_MANAGER_NAMESPACE }}" # Namespace for cert-manager 16 | chart_repo_url: "{{ CERT_MANAGER_CHART_URL }}" # Helm chart repository URL 17 | chart_ref: "{{ CERT_MANAGER_CHART_NAME }}" # Helm chart name 18 | chart_version: "{{ CERT_MANAGER_CHART_VERSION }}" # Chart version to deploy 19 | values: "{{ CERT_MANAGER_CONFIG }}" # Custom values for the chart 20 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 21 | create_namespace: true # Create namespace if it doesn't exist 22 | wait: true # Wait for deployment to complete 23 | when: 24 | - V4_CFG_TLS_GENERATOR is defined # Only if TLS generator is defined 25 | - V4_CFG_TLS_GENERATOR == 'cert-manager' # Only if cert-manager is the generator 26 | tags: 27 | - install 28 | - update 29 | 30 | # Remove the cert-manager Helm release 31 | - name: Remove cert-manager 32 | kubernetes.core.helm: 33 | name: "{{ CERT_MANAGER_NAME }}" # Name of the Helm release 34 | namespace: "{{ CERT_MANAGER_NAMESPACE }}" # Namespace for cert-manager 35 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 36 | wait: true # Wait for removal to complete 37 | values: "{{ CERT_MANAGER_CONFIG }}" # Use the same values as install (for idempotency) 38 | state: absent # Ensure the release is removed 39 | tags: 40 | - uninstall 41 | 42 | # Remove the cert-manager namespace from the cluster 43 | - name: Remove {{ CERT_MANAGER_NAMESPACE }} namespace 44 | kubernetes.core.k8s: 45 | api_version: v1 # Kubernetes API version 46 | kind: Namespace # Resource kind 47 | name: "{{ CERT_MANAGER_NAMESPACE }}" # Namespace to remove 48 | wait: true # Wait for deletion 49 | state: absent # Ensure the namespace is deleted 50 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 51 | tags: 52 | - uninstall 53 | -------------------------------------------------------------------------------- /roles/baseline/tasks/cluster-autoscaler.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the cluster-autoscaler setup tasks for the baseline role. 6 | # Chart Repo URL: https://kubernetes.github.io/autoscaler/ 7 | # Container registry: registry.k8s.io 8 | # Chart Source: https://github.com/kubernetes/autoscaler/tree/master/charts/cluster-autoscaler 9 | # Purpose: Installs and manages the Kubernetes Cluster Autoscaler for automatic node scaling. 10 | 11 | # NOTE: This file is intended for use with cloud providers that support the Kubernetes Cluster Autoscaler, 12 | # such as AWS, Azure, and GCP. Configuration and values may need to be adjusted for your specific provider. 13 | 14 | # Deploy the cluster-autoscaler using Helm 15 | - name: Deploy cluster-autoscaler 16 | kubernetes.core.helm: 17 | name: "{{ CLUSTER_AUTOSCALER_NAME }}" # Name of the Helm release 18 | namespace: "{{ CLUSTER_AUTOSCALER_NAMESPACE }}" # Namespace for the autoscaler 19 | chart_repo_url: "{{ CLUSTER_AUTOSCALER_CHART_URL }}" # Helm chart repository URL 20 | chart_ref: "{{ CLUSTER_AUTOSCALER_CHART_NAME }}" # Helm chart name 21 | chart_version: "{{ CLUSTER_AUTOSCALER_CHART_VERSION }}" # Chart version to deploy 22 | values: "{{ CLUSTER_AUTOSCALER_CONFIG }}" # Custom values for the chart 23 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 24 | wait: true # Wait for deployment to complete 25 | when: 26 | - CLUSTER_AUTOSCALER_ENABLED # Only if autoscaler is enabled 27 | tags: 28 | - install 29 | - update 30 | 31 | # Remove the cluster-autoscaler Helm release 32 | - name: Remove cluster-autoscaler 33 | kubernetes.core.helm: 34 | name: "{{ CLUSTER_AUTOSCALER_NAME }}" # Name of the Helm release 35 | namespace: "{{ CLUSTER_AUTOSCALER_NAMESPACE }}" # Namespace for the autoscaler 36 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 37 | wait: true # Wait for removal to complete 38 | values: "{{ CLUSTER_AUTOSCALER_CONFIG }}" # Use the same values as install (for idempotency) 39 | state: absent # Ensure the release is removed 40 | tags: 41 | - uninstall 42 | -------------------------------------------------------------------------------- /roles/baseline/tasks/contour.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the Contour ingress controller setup tasks for the baseline role. 6 | # It is included from main.yaml when Contour is required. 7 | # NOTE: This file supports deploying Contour on any Kubernetes cluster, including major 8 | # cloud providers such as AWS, Azure, and GCP. Configuration is conditional per provider. 9 | # There is no provider-specific logic here; any provider-specific differences 10 | # should be handled in the Helm values (CONTOUR_CONFIG). 11 | 12 | # Name: contour 13 | # Chart URL: https://projectcontour.io/ 14 | # Container registry: docker.io 15 | # Purpose: Alternative ingress controller (if selected). 16 | 17 | # Deploy the Contour ingress controller using Helm 18 | - name: Deploy contour 19 | kubernetes.core.helm: 20 | name: "{{ CONTOUR_NAME }}" # Name of the Helm release 21 | namespace: "{{ CONTOUR_NAMESPACE }}" # Namespace for Contour 22 | chart_repo_url: "{{ CONTOUR_CHART_URL }}" # Helm chart repository URL 23 | chart_ref: "{{ CONTOUR_CHART_NAME }}" # Helm chart name 24 | chart_version: "{{ CONTOUR_CHART_VERSION }}" # Chart version to deploy 25 | values: "{{ CONTOUR_CONFIG }}" # Custom values for the chart 26 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 27 | create_namespace: true # Create namespace if it doesn't exist 28 | wait: true # Wait for deployment to complete 29 | tags: 30 | - install 31 | - update 32 | 33 | # Remove the Contour ingress controller Helm release 34 | - name: Remove contour 35 | kubernetes.core.helm: 36 | name: "{{ CONTOUR_NAME }}" # Name of the Helm release 37 | namespace: "{{ CONTOUR_NAMESPACE }}" # Namespace for Contour 38 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 39 | wait: true # Wait for removal to complete 40 | values: "{{ CONTOUR_CONFIG }}" # Use the same values as install (for idempotency) 41 | state: absent # Ensure the release is removed 42 | tags: 43 | - uninstall 44 | 45 | # Remove the Contour namespace from the cluster 46 | - name: Remove {{ CONTOUR_NAMESPACE }} namespace 47 | kubernetes.core.k8s: 48 | api_version: v1 # Kubernetes API version 49 | kind: Namespace # Resource kind 50 | name: "{{ CONTOUR_NAMESPACE }}" # Namespace to remove 51 | wait: true # Wait for deletion 52 | wait_timeout: 600 # Timeout for deletion 53 | state: absent # Ensure the namespace is deleted 54 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 55 | tags: 56 | - uninstall 57 | -------------------------------------------------------------------------------- /roles/baseline/tasks/ebs-csi-driver.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the ebs-csi-driver setup tasks for the baseline role. 6 | # Chart Repo URL: https://kubernetes-sigs.github.io/aws-ebs-csi-driver/ 7 | # Container registry: public.ecr.aws 8 | # Chart Source: https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/charts 9 | # Purpose: Installs and manages the AWS EBS CSI driver for dynamic EBS volume provisioning on AWS. 10 | 11 | - name: Deploy ebs-csi-driver 12 | kubernetes.core.helm: 13 | name: "{{ EBS_CSI_DRIVER_NAME }}" 14 | namespace: "{{ EBS_CSI_DRIVER_NAMESPACE }}" 15 | chart_repo_url: "{{ EBS_CSI_DRIVER_CHART_URL }}" 16 | chart_ref: "{{ EBS_CSI_DRIVER_CHART_NAME }}" 17 | chart_version: "{{ EBS_CSI_DRIVER_CHART_VERSION }}" 18 | values: "{{ EBS_CSI_DRIVER_CONFIG }}" 19 | kubeconfig: "{{ KUBECONFIG }}" 20 | wait: true 21 | when: 22 | - EBS_CSI_DRIVER_ENABLED 23 | tags: 24 | - install 25 | - update 26 | 27 | - name: Remove ebs-csi-driver 28 | kubernetes.core.helm: 29 | name: "{{ EBS_CSI_DRIVER_NAME }}" 30 | namespace: "{{ EBS_CSI_DRIVER_NAMESPACE }}" 31 | kubeconfig: "{{ KUBECONFIG }}" 32 | wait: true 33 | values: "{{ EBS_CSI_DRIVER_CONFIG }}" 34 | state: absent 35 | tags: 36 | - uninstall 37 | -------------------------------------------------------------------------------- /roles/baseline/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file includes baseline setup tasks for the cluster, such as storage, ingress, and version checks. 6 | # Each block is conditionally included based on configuration variables and tags. 7 | 8 | # Include NFS CSI provisioner tasks if RWX filestore is managed 9 | - name: Include nfs.csi.k8s.io 10 | include_tasks: 11 | file: nfs-csi-provisioner.yaml 12 | when: 13 | - V4_CFG_RWX_FILESTORE_ENDPOINT is defined 14 | - V4_CFG_RWX_FILESTORE_PATH is defined 15 | - V4_CFG_MANAGE_STORAGE is defined 16 | - V4_CFG_MANAGE_STORAGE|bool 17 | tags: 18 | - baseline 19 | 20 | # Include ingress-nginx tasks if ingress type is 'ingress' or 'nginx' tag is present 21 | - name: Include ingress nginx 22 | include_tasks: 23 | file: ingress-nginx.yaml 24 | when: 25 | - (V4_CFG_INGRESS_TYPE == 'ingress') or ('nginx' in ansible_run_tags) 26 | tags: 27 | - baseline 28 | 29 | # Include Contour ingress tasks if ingress type is 'contour' or 'contour' tag is present 30 | - name: Include contour 31 | include_tasks: 32 | file: contour.yaml 33 | when: 34 | - (V4_CFG_INGRESS_TYPE == 'contour') or ('contour' in ansible_run_tags) 35 | tags: 36 | - baseline 37 | 38 | # Include Istio role if ingress type is 'istio' or 'istio' tag is present 39 | - name: Include istio 40 | include_role: 41 | name: istio 42 | when: 43 | - (V4_CFG_INGRESS_TYPE == 'istio') or ('istio' in ansible_run_tags) 44 | tags: 45 | - baseline 46 | 47 | # Retrieve Kubernetes cluster version and set K8S_VERSION fact 48 | - name: Lookup K8s version info 49 | tags: 50 | - baseline 51 | block: 52 | - name: Retrieve K8s cluster information 53 | kubernetes.core.k8s_cluster_info: 54 | kubeconfig: "{{ KUBECONFIG }}" 55 | register: cluster_info 56 | - name: Set the K8s server version 57 | set_fact: 58 | K8S_VERSION: "{{ cluster_info.version.server.kubernetes.major + '.' + cluster_info.version.server.kubernetes.minor | regex_replace('\\+$', '') }}" 59 | 60 | # Include cluster autoscaler tasks for AWS if required variables are set 61 | - name: Include cluster-autoscaler 62 | include_tasks: 63 | file: cluster-autoscaler.yaml 64 | when: 65 | - PROVIDER == "aws" 66 | - CLUSTER_AUTOSCALER_ACCOUNT is defined 67 | - CLUSTER_AUTOSCALER_ACCOUNT is not none 68 | tags: 69 | - baseline 70 | 71 | # Include EBS CSI driver tasks for AWS if K8S version is >= 1.23 and required variables are set 72 | - name: Include ebs-csi-driver 73 | include_tasks: 74 | file: ebs-csi-driver.yaml 75 | when: 76 | - PROVIDER == "aws" 77 | - K8S_VERSION|float >= 1.23 78 | - EBS_CSI_DRIVER_ACCOUNT is defined 79 | - EBS_CSI_DRIVER_ACCOUNT is not none 80 | tags: 81 | - baseline 82 | 83 | # Include Azure StorageClasses tasks if provider is Azure 84 | - name: Include StorageClasses 85 | include_tasks: 86 | file: storage-classes.yaml 87 | when: 88 | - PROVIDER == "azure" 89 | tags: 90 | - baseline 91 | 92 | # Always include cert-manager tasks 93 | - name: Include cert manager 94 | include_tasks: 95 | file: cert-manager.yaml 96 | tags: 97 | - baseline 98 | 99 | # The metrics-server tasks are only applicable for AWS 100 | - name: Include metrics-server 101 | include_tasks: 102 | file: metrics-server.yaml 103 | tags: 104 | - baseline 105 | when: 106 | - PROVIDER in ["aws"] 107 | -------------------------------------------------------------------------------- /roles/baseline/tasks/metrics-server.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the metrics-server setup tasks for the baseline role. 6 | # Chart Repo URL: https://kubernetes-sigs.github.io/metrics-server/ 7 | # Container registry: registry.k8s.io 8 | # Chart Source: https://github.com/kubernetes-sigs/metrics-server/tree/master/charts/metrics-server 9 | # Purpose: Installs and manages metrics-server for resource metrics collection in Kubernetes. 10 | 11 | # Name: metrics-server 12 | # Chart URL: https://github.com/kubernetes-sigs/metrics-server/tree/master/charts/metrics-server 13 | # Purpose: Collects resource metrics from K8s nodes and pods. 14 | 15 | # Check if the metrics-server service exists in the kube-system namespace 16 | - name: Check for metrics service 17 | kubernetes.core.k8s_info: 18 | api_version: v1 # Kubernetes API version 19 | kind: Service # Resource kind 20 | name: metrics-server # Name of the service to check 21 | namespace: kube-system # Namespace where metrics-server should be 22 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 23 | register: metrics_service # Register the result for later use 24 | when: 25 | - METRICS_SERVER_ENABLED # Only if metrics-server is enabled 26 | tags: 27 | - install 28 | - update 29 | - uninstall 30 | 31 | # Deploy the metrics-server using Helm if it is not already present 32 | - name: Deploy metrics-server 33 | kubernetes.core.helm: 34 | name: "{{ METRICS_SERVER_NAME }}" # Name of the Helm release 35 | namespace: kube-system # Namespace for metrics-server 36 | chart_repo_url: "{{ METRICS_SERVER_CHART_URL }}" # Helm chart repository URL 37 | chart_ref: "{{ METRICS_SERVER_CHART_NAME }}" # Helm chart name 38 | chart_version: "{{ METRICS_SERVER_CHART_VERSION }}" # Chart version to deploy 39 | values: "{{ METRICS_SERVER_CONFIG }}" # Custom values for the chart 40 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 41 | wait: true # Wait for deployment to complete 42 | tags: 43 | - install 44 | - update 45 | when: 46 | - ('resources' not in metrics_service) or ((metrics_service.resources | length) == 0) # Only if not already present 47 | - METRICS_SERVER_ENABLED 48 | 49 | # Remove the metrics-server Helm release if present (uninstall) 50 | - name: Remove metrics-server 51 | kubernetes.core.helm: 52 | name: "{{ METRICS_SERVER_NAME }}" # Name of the Helm release 53 | namespace: kube-system # Namespace for metrics-server 54 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 55 | values: "{{ METRICS_SERVER_CONFIG }}" # Use the same values as install (for idempotency) 56 | state: absent # Ensure the release is removed 57 | wait: true # Wait for removal to complete 58 | tags: 59 | - uninstall 60 | when: 61 | - METRICS_SERVER_ENABLED 62 | -------------------------------------------------------------------------------- /roles/baseline/tasks/storage-classes.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the storage class setup tasks for the baseline role. 6 | # It is included from main.yaml when storage-classes are required. 7 | 8 | # Create the Azure storage class for RabbitMQ if required 9 | - name: Create Azure storage class for RabbitMQ 10 | kubernetes.core.k8s: 11 | api_version: v1 # Kubernetes API version 12 | definition: "{{ AZURE_RABBITMQ_STORAGE_CLASS }}" # StorageClass definition for RabbitMQ 13 | wait: true # Wait for resource creation 14 | wait_timeout: 600 # Timeout for creation 15 | state: present # Ensure the resource is present 16 | kubeconfig: "{{ KUBECONFIG }}" # Kubeconfig for cluster access 17 | when: 18 | - PROVIDER == "azure" # Only for Azure provider 19 | - CREATE_AZURE_RABBITMQ_STORAGE_CLASS # Only if creation is enabled 20 | tags: 21 | - install 22 | 23 | # Create the Azure storage class for Postgres if required 24 | - name: Create Azure storage class for Postgres 25 | kubernetes.core.k8s: 26 | api_version: v1 # Kubernetes API version 27 | definition: "{{ AZURE_CRUNCHY_STORAGE_CLASS }}" # StorageClass definition for Postgres 28 | wait: true 29 | wait_timeout: 600 30 | state: present 31 | kubeconfig: "{{ KUBECONFIG }}" 32 | when: 33 | - PROVIDER == "azure" 34 | - CREATE_AZURE_CRUNCHY_STORAGE_CLASS 35 | tags: 36 | - install 37 | 38 | # Remove the Azure storage class for RabbitMQ if required (uninstall) 39 | - name: Remove Azure storage class for RabbitMQ 40 | kubernetes.core.k8s: 41 | api_version: v1 42 | definition: "{{ AZURE_RABBITMQ_STORAGE_CLASS }}" 43 | wait: true 44 | wait_timeout: 600 45 | state: absent # Ensure the resource is absent 46 | kubeconfig: "{{ KUBECONFIG }}" 47 | when: 48 | - PROVIDER == "azure" 49 | - CREATE_AZURE_RABBITMQ_STORAGE_CLASS 50 | tags: 51 | - uninstall 52 | 53 | # Remove the Azure storage class for Postgres if required (uninstall) 54 | - name: Remove Azure storage class for Postgres 55 | kubernetes.core.k8s: 56 | api_version: v1 57 | definition: "{{ AZURE_CRUNCHY_STORAGE_CLASS }}" 58 | wait: true 59 | wait_timeout: 600 60 | state: absent 61 | kubeconfig: "{{ KUBECONFIG }}" 62 | when: 63 | - PROVIDER == "azure" 64 | - CREATE_AZURE_CRUNCHY_STORAGE_CLASS 65 | tags: 66 | - uninstall 67 | -------------------------------------------------------------------------------- /roles/common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | V4_CFG_POSTGRES_SERVERS: 6 | default: {} 7 | 8 | ## NIST Features 9 | V4_CFG_NIST_FEATURES_ENABLED: false 10 | -------------------------------------------------------------------------------- /roles/common/lookup_plugins/tfstate.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | from __future__ import (absolute_import, division, print_function) 6 | __metaclass__ = type 7 | 8 | import os 9 | import subprocess 10 | import json 11 | 12 | 13 | from ansible.plugins.lookup import LookupBase 14 | from ansible.module_utils._text import to_native, to_text 15 | 16 | class LookupModule(LookupBase): 17 | def run(self, terms, variables=None, **kwargs): 18 | ret = [] 19 | for term in terms: 20 | tmp_source = self._loader.get_real_file(term) 21 | with open(tmp_source, 'r') as jsonfile: 22 | jsonfile.seek(0) 23 | data = json.load(jsonfile) 24 | ret.append(data["outputs"]) 25 | return ret 26 | -------------------------------------------------------------------------------- /roles/istio/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /roles/istio/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | target_arch: x86_64 6 | loadBalancerSourceRanges: ["109.232.56.224/27", "149.173.0.0/16", "194.206.69.176/28"] 7 | 8 | istio_ver: 1.6.8 9 | 10 | istio_config: | 11 | {% for loadBalancerSourceRange in loadBalancerSourceRanges%} --set values.gateways.istio-ingressgateway.loadBalancerSourceRanges[{{ loop.index }}]="{{ loadBalancerSourceRange }}" {% endfor %} --set values.sidecarInjectorWebhook.rewriteAppHTTPProbe=true --set values.global.mtls.enabled=true --set values.global.controlPlaneSecurityEnabled=true --set values.grafana.enabled=true --set values.tracing.enabled=true --set values.kiali.enabled=true --set values.prometheus.enabled=true --set "values.kiali.dashboard.jaegerURL=http://jaeger-query:16686" --set "values.kiali.dashboard.grafanaURL=http://grafana:3000" --set values.global.sds.enabled=true --set values.gateways.istio-ingressgateway.enabled=true --set values.gateways.istio-ingressgateway.sds.enabled=true 12 | 13 | kiali_username: admin 14 | kiali_password: admin 15 | grafana_username: admin 16 | grafana_password: admin 17 | 18 | grafana_ingress_enabled: false 19 | grafana_ingress_host: grafana.example.org 20 | 21 | prometheus_ingress_enabled: false 22 | prometheus_ingress_host: prometheus.example.org 23 | 24 | kiali_ingress_enabled: false 25 | kiali_ingress_host: kiali.example.org 26 | 27 | tracing_ingress_enabled: false 28 | tracing_ingress_host: tracing.example.org 29 | -------------------------------------------------------------------------------- /roles/istio/templates/grafana-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: grafana 5 | namespace: istio-system 6 | labels: 7 | app: grafana 8 | type: Opaque 9 | stringData: 10 | username: {{ grafana_username }} 11 | passphrase: {{ grafana_password }} 12 | -------------------------------------------------------------------------------- /roles/istio/templates/kiali-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: kiali 5 | namespace: istio-system 6 | labels: 7 | app: kiali 8 | type: Opaque 9 | stringData: 10 | username: {{ kiali_username }} 11 | passphrase: {{ kiali_password }} 12 | -------------------------------------------------------------------------------- /roles/istio/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/istio/tests/test.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | - hosts: localhost 6 | remote_user: root 7 | roles: 8 | - deploy 9 | -------------------------------------------------------------------------------- /roles/istio/vars/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # vars file for deploy 6 | -------------------------------------------------------------------------------- /roles/jump-server/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | JUMP_SVR_RWX_FILESTORE_PATH: /viya-share 6 | folder_owner: nobody 7 | folder_group: nobody 8 | -------------------------------------------------------------------------------- /roles/jump-server/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains tasks for configuring the jump server host and preparing shared folders. 6 | 7 | # Add the jump server host to the Ansible inventory dynamically 8 | - name: jump-server - add host # noqa: name[casing] 9 | add_host: 10 | hostname: "{{ JUMP_SVR_HOST }}" 11 | ansible_ssh_user: "{{ JUMP_SVR_USER }}" 12 | ansible_ssh_private_key_file: "{{ JUMP_SVR_PRIVATE_KEY }}" 13 | ansible_ssh_common_args: -o UserKnownHostsFile=/dev/null 14 | groups: 15 | - jump 16 | tags: 17 | - install 18 | 19 | # Lookup all groups on the jump server 20 | - name: jump-server - lookup groups # noqa: name[casing] 21 | getent: 22 | database: group 23 | delegate_to: "{{ groups['jump'][0] }}" 24 | become: true 25 | tags: 26 | - install 27 | 28 | # Set folder group/owner to nfsnobody if present 29 | - name: jump-server - group nfsnobody # noqa: name[casing] 30 | set_fact: 31 | folder_group: nfsnobody 32 | folder_owner: nfsnobody 33 | when: 34 | - '"nfsnobody" in ansible_facts.getent_group' 35 | tags: 36 | - install 37 | 38 | # Set folder group to nogroup if present 39 | - name: jump-server - group nogroup # noqa: name[casing] 40 | set_fact: 41 | folder_group: nogroup 42 | when: 43 | - '"nogroup" in ansible_facts.getent_group' 44 | tags: 45 | - install 46 | 47 | # Create shared folders for bin, homes, data, astores on the jump server 48 | - name: jump-server - create folders # noqa: name[casing] 49 | file: 50 | state: directory 51 | path: "{{ JUMP_SVR_RWX_FILESTORE_PATH | replace('/$', '') }}/{{ hostvars['localhost']['NAMESPACE'] }}/{{ item }}" 52 | owner: "{{ folder_owner }}" 53 | group: "{{ folder_group }}" 54 | mode: "0777" 55 | with_items: 56 | - bin 57 | - homes 58 | - data 59 | - astores 60 | delegate_to: "{{ groups['jump'][0] }}" 61 | become: true 62 | tags: 63 | - install 64 | -------------------------------------------------------------------------------- /roles/multi-tenancy/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | ## Multi-tenant 6 | 7 | # Updating HOST to remove https 8 | V4_CFG_CR_URL: https://cr.sas.com 9 | V4_CFG_CR_HOST: '{{ V4_CFG_CR_URL | regex_replace("^https?:\/\/(.*)\/?", "\1") }}' 10 | 11 | V4_CFG_CR_USER: null 12 | V4_CFG_CR_PASSWORD: null 13 | 14 | # Multi-tenant is enabled within SAS Viya deployment 15 | V4MT_ENABLE: false 16 | 17 | # SAS Viya supports two modes of data isolation (schemaPerApplicationTenant and databasePerTenant) for tenant data. 18 | # Set V4MT_MODE to either schema or database. schemaPerApplicationTenant Mode is enabled by default. 19 | V4MT_MODE: schema 20 | 21 | V4MT_TENANT_IDS: null 22 | 23 | # Optional job parameter 24 | V4MT_PROVIDER_PASSWORD: null 25 | 26 | # CAS customization values 27 | V4MT_TENANT_CAS_CUSTOMIZATION: {} 28 | # Setting values for retry and delay to 60 seconds for Onboard and Offboard job 29 | V4MT_ONBOARD_RETRY: 60 30 | V4MT_ONBOARD_DELAY: 60 31 | V4MT_OFFBOARD_RETRY: 60 32 | V4MT_OFFBOARD_DELAY: 60 33 | -------------------------------------------------------------------------------- /roles/multi-tenancy/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the main tasks for the multi-tenancy role, handling onboarding, offboarding, and setup for tenants. 6 | # Each block is conditionally included based on configuration variables and tags. 7 | 8 | # Include multi-tenant setup tasks 9 | # This task includes the setup tasks for multi-tenancy, which are required for both onboarding and offboarding. 10 | - name: Multi-tenancy - include setup tasks 11 | include_tasks: multi-tenant-setup.yaml 12 | # Include the setup tasks for multi-tenancy 13 | when: V4MT_ENABLE 14 | tags: 15 | - onboard 16 | - offboard 17 | 18 | # Include Orchestration Tooling tasks 19 | # This task includes common orchestration tooling tasks that are applicable for both onboarding and offboarding. 20 | - name: Include Orchestration Tooling 21 | include_tasks: ../../orchestration-common/tasks/orchestration_tooling.yaml 22 | tags: 23 | - onboard 24 | - cas-onboard 25 | - offboard 26 | 27 | # Include onboarding and offboarding tasks for multi-tenancy 28 | - name: Multi-tenancy - include onboard/offboard tasks 29 | include_tasks: multi-tenant-onboard-offboard.yaml 30 | # Include the onboarding and offboarding tasks for tenants 31 | when: V4MT_ENABLE 32 | tags: 33 | - onboard 34 | - offboard 35 | 36 | # Include tenant CAS customizations 37 | # This task includes the tenant CAS customizations, which are necessary for both cas onboarding and offboarding. 38 | - name: Multi-tenancy - include CAS server onboard/offboard tasks 39 | include_tasks: onboard-offboard-cas-servers.yaml 40 | # Include the CAS server onboarding and offboarding tasks 41 | when: V4MT_ENABLE 42 | tags: 43 | - cas-onboard 44 | - offboard 45 | -------------------------------------------------------------------------------- /roles/multi-tenancy/tasks/onboard-offboard-cas-servers.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the onboarding and offboarding tasks for CAS servers in the multi-tenancy role. 6 | # It is included from main.yaml when onboarding or offboarding CAS servers for tenants. 7 | 8 | # Update Resources in Kustomization.yaml 9 | - name: Check if cas resources present 10 | lineinfile: 11 | path: "{{ DEPLOY_DIR }}/kustomization.yaml" 12 | line: "- site-config/cas-{{ item | trim }}-default" 13 | state: present 14 | check_mode: true 15 | register: out 16 | with_items: "{{ V4MT_TENANT_IDS.split(',') }}" 17 | tags: 18 | - cas-onboard 19 | 20 | - name: Add cas resources 21 | lineinfile: 22 | path: "{{ DEPLOY_DIR }}/kustomization.yaml" 23 | insertafter: "resources:" 24 | line: "- site-config/cas-{{ item | trim }}-default" 25 | state: present 26 | with_items: "{{ V4MT_TENANT_IDS.split(',') }}" 27 | when: out.changed 28 | tags: 29 | - cas-onboard 30 | 31 | # Remove all the tenant cas resources 32 | - name: Remove cas resources 33 | lineinfile: 34 | path: "{{ DEPLOY_DIR }}/kustomization.yaml" 35 | regexp: .*site-config/cas-{{ item | trim }}-default.*$ 36 | state: absent 37 | with_items: "{{ V4MT_TENANT_IDS.split(',') }}" 38 | tags: 39 | - offboard 40 | 41 | ## Add tenant specific pod templates 42 | - name: Check if tenant resources are present 43 | lineinfile: 44 | path: "{{ DEPLOY_DIR }}/kustomization.yaml" 45 | line: "- site-config/multi-tenant/{{ item | trim }}" 46 | state: present 47 | check_mode: true 48 | register: result 49 | with_items: "{{ V4MT_TENANT_IDS.split(',') }}" 50 | when: V4_CFG_CADENCE_VERSION is version('2023.03', ">=") or V4_CFG_CADENCE_NAME|lower == "fast" 51 | tags: 52 | - cas-onboard 53 | 54 | - name: Add tenant directories to resources 55 | lineinfile: 56 | path: "{{ DEPLOY_DIR }}/kustomization.yaml" 57 | insertafter: "resources:" 58 | line: "- site-config/multi-tenant/{{ item | trim }}" 59 | state: present 60 | with_items: "{{ V4MT_TENANT_IDS.split(',') }}" 61 | when: 62 | - result.changed 63 | - V4_CFG_CADENCE_VERSION is version('2023.03', ">=") or V4_CFG_CADENCE_NAME|lower == "fast" 64 | tags: 65 | - cas-onboard 66 | 67 | # On offboard remove all the tenant pod template resources 68 | - name: Remove all tenant resources 69 | lineinfile: 70 | path: "{{ DEPLOY_DIR }}/kustomization.yaml" 71 | regexp: .*site-config/multi-tenant/{{ item | trim }}.*$ 72 | state: absent 73 | with_items: "{{ V4MT_TENANT_IDS.split(',') }}" 74 | when: V4_CFG_CADENCE_VERSION is version('2023.03', ">=") or V4_CFG_CADENCE_NAME|lower == "fast" 75 | tags: 76 | - offboard 77 | 78 | # Offboard CAS servers 79 | - name: Kubectl delete cas servers for tenants 80 | ansible.builtin.shell: | 81 | echo {{ item }} 82 | kubectl --kubeconfig {{ KUBECONFIG }} -n {{ NAMESPACE }} delete casdeployment -l sas.com/tenant={{ item | trim }} 83 | with_items: '{{ V4MT_TENANT_IDS.split(",") | replace(" ", "") }}' 84 | tags: 85 | - offboard 86 | 87 | # After offboard cas servers delete the cas tenant directories 88 | - name: Delete cas tenant directory 89 | file: 90 | state: absent 91 | path: "{{ DEPLOY_DIR }}/site-config/cas-{{ item | trim }}-default" 92 | with_items: '{{ V4MT_TENANT_IDS.split(",") | replace(" ", "") }}' 93 | tags: 94 | - offboard 95 | 96 | # On offboard delete the tenant pod template directories 97 | # Remove the tenant-specific pod template directory if it exists 98 | - name: Delete tenant pod template directory 99 | file: 100 | state: absent 101 | path: "{{ DEPLOY_DIR }}/site-config/multi-tenant/{{ item | trim }}" 102 | with_items: '{{ V4MT_TENANT_IDS.split(",") | replace(" ", "") }}' 103 | when: V4_CFG_CADENCE_VERSION is version('2023.03', ">=") or V4_CFG_CADENCE_NAME|lower == "fast" 104 | tags: 105 | - offboard 106 | 107 | # Delete the sasdeployment.yaml file 108 | - name: Delete sasdeployment.yaml 109 | file: 110 | state: absent 111 | path: "{{ DEPLOY_DIR }}/sasdeployment.yaml" 112 | tags: 113 | - cas-onboard 114 | - offboard 115 | -------------------------------------------------------------------------------- /roles/multi-tenancy/tasks/tenant-cas-customizations.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the tenant CAS customizations tasks for the multi-tenancy role. 6 | # It is included from main.yaml when tenant-specific CAS customizations are required. 7 | 8 | # Main block for updating tenant CAS customizations 9 | - name: Update tenant cas customizations 10 | when: V4MT_TENANT_IDS is search(tenant) # Only run if the tenant is present in the list 11 | tags: 12 | - onboard 13 | block: 14 | # Run the create-cas-server.sh script to set up MPP workers and backup controller for the tenant 15 | - name: Tenant cas - MPP workers 16 | command: 17 | cmd: "{{ DEPLOY_DIR }}/site-config/create-cas-server.sh --tenant {{ tenant }} --output {{ DEPLOY_DIR }}/site-config --workers {{ settings.worker_count if (settings.worker_count is defined and settings.worker_count is not none) else 0 }} --backup {{ 1 if (settings.backup_controller_enabled is defined) and (settings.backup_controller_enabled | bool == True) else 0 }}" 18 | 19 | # Copy the CPU/memory management template if user-defined resources are specified 20 | - name: Tenant cas user-defined resources - copy template 21 | copy: 22 | src: "{{ role_path }}/templates/cas-manage-cpu-and-memory.yaml" # Source template for CPU/memory 23 | dest: "{{ DEPLOY_DIR }}/site-config/cas-{{ tenant }}-default/cas-manage-cpu-and-memory.yaml" # Destination path 24 | mode: "0660" 25 | when: 26 | - settings.memory is defined and settings.memory is not none # Only if memory is specified 27 | - settings.cpus is defined and settings.cpus is not none # Only if CPUs are specified 28 | 29 | # Replace placeholders in the copied template with actual values for memory, CPUs, and server name 30 | - name: Tenant cas user-defined resources - update 31 | replace: 32 | path: "{{ DEPLOY_DIR }}/site-config/cas-{{ tenant }}-default/cas-manage-cpu-and-memory.yaml" 33 | regexp: "{{ outer_item.regexp }}" 34 | replace: "{{ outer_item.replace }}" 35 | with_items: 36 | - { regexp: "{% raw %}{{ AMOUNT-OF-RAM }}{% endraw %}", replace: "{{ settings.memory }}" } 37 | - { regexp: "{% raw %}{{ NUMBER-OF-CORES }}{% endraw %}", replace: "{{ settings.cpus }}" } 38 | - { regexp: "{% raw %}{{ NAME-OF-SERVER }}{% endraw %}", replace: "{{ tenant }}-default" } 39 | loop_control: 40 | loop_var: outer_item 41 | when: 42 | - settings.memory is defined and settings.memory is not none 43 | - settings.cpus is defined and settings.cpus is not none 44 | 45 | # Add the user-defined resource transformer to the tenant's kustomization.yaml 46 | - name: Add tenant cas user-defined resources to kustomization 47 | lineinfile: 48 | path: "{{ DEPLOY_DIR }}/site-config/cas-{{ tenant }}-default/kustomization.yaml" 49 | insertafter: "transformers:" 50 | line: "- cas-manage-cpu-and-memory.yaml" 51 | when: 52 | - settings.memory is defined and settings.memory is not none 53 | - settings.cpus is defined and settings.cpus is not none 54 | 55 | # Copy the external services template if load balancer is enabled and source ranges are specified 56 | - name: Tenant cas - external services copy template 57 | copy: 58 | src: "{{ role_path }}/templates/cas-enable-external-services.yaml" # Source template for external services 59 | dest: "{{ DEPLOY_DIR }}/site-config/cas-{{ tenant }}-default" # Destination directory 60 | mode: "0660" 61 | when: 62 | - settings.loadbalancer_enabled is defined and settings.loadbalancer_enabled is true 63 | - settings.loadbalancer_source_ranges is defined and settings.loadbalancer_source_ranges is not none 64 | 65 | # Replace placeholders in the external services template with actual values 66 | - name: Tenant cas external services - update 67 | replace: 68 | path: "{{ DEPLOY_DIR }}/site-config/cas-{{ tenant }}-default/cas-enable-external-services.yaml" 69 | regexp: "{{ outer_item.regexp }}" 70 | replace: "{{ outer_item.replace }}" 71 | with_items: 72 | - { regexp: "{% raw %}{{ LOADBALANCER_SOURCE_RANGES }}{% endraw %}", replace: "{{ settings.loadbalancer_source_ranges }}" } 73 | - { regexp: "{% raw %}{{ NAME-OF-SERVER }}{% endraw %}", replace: "{{ tenant }}-default" } 74 | loop_control: 75 | loop_var: outer_item 76 | when: 77 | - settings.loadbalancer_enabled is defined and settings.loadbalancer_enabled is true 78 | - settings.loadbalancer_source_ranges is defined and settings.loadbalancer_source_ranges is not none 79 | 80 | # Add the external services transformer to the tenant's kustomization.yaml 81 | - name: Add tenant cas external services to kustomization 82 | lineinfile: 83 | path: "{{ DEPLOY_DIR }}/site-config/cas-{{ tenant }}-default/kustomization.yaml" 84 | insertafter: "transformers:" 85 | line: "- cas-enable-external-services.yaml" 86 | when: 87 | - settings.loadbalancer_enabled is defined and settings.loadbalancer_enabled is true 88 | - settings.loadbalancer_source_ranges is defined and settings.loadbalancer_source_ranges is not none 89 | -------------------------------------------------------------------------------- /roles/multi-tenancy/tasks/tenant-pod-templates.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the tenant pod template customization tasks for the multi-tenancy role. 6 | # It is included from main.yaml when tenant-specific pod template customizations are required. 7 | 8 | - name: FileGenerator updates for tenant-specific resources 9 | when: V4MT_TENANT_IDS is search(tenant) 10 | tags: 11 | - onboard 12 | block: 13 | - name: Delete tenant-specific resource directories if present 14 | file: 15 | state: absent 16 | path: "{{ DEPLOY_DIR }}/site-config/multi-tenant/{{ tenant }}" 17 | - name: Create a new directory for each tenant under $deploy/site-config/multi-tenant/ 18 | file: 19 | state: directory 20 | dest: "{{ DEPLOY_DIR }}/site-config/multi-tenant/{{ tenant }}" 21 | mode: "0770" 22 | - name: Copy - sas-programming-environment files 23 | copy: 24 | src: "{{ DEPLOY_DIR }}/sas-bases/examples/multi-tenant/sas-programming-environment/" 25 | dest: "{{ DEPLOY_DIR }}/site-config/multi-tenant/{{ tenant }}" 26 | mode: "0770" 27 | - name: List all the pod templates to be updated 28 | find: 29 | paths: "{{ DEPLOY_DIR }}/site-config/multi-tenant/{{ item }}" 30 | recurse: true 31 | register: result 32 | - name: Replace all occurrences of SAS-TENANT-ID with the ID of the tenant 33 | replace: 34 | path: "{{ outer_item.path }}" 35 | regexp: "{% raw %}{{ SAS-TENANT-ID }}{% endraw %}" 36 | replace: "{{ tenant }}" 37 | with_items: "{{ result.files }}" 38 | loop_control: 39 | loop_var: outer_item 40 | -------------------------------------------------------------------------------- /roles/multi-tenancy/templates/cas-enable-external-services.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: cas-enable-external-services 6 | patch: |- 7 | - op: add 8 | path: /spec/publishBinaryService 9 | value: true 10 | - op: add 11 | path: /spec/serviceTemplate 12 | value: 13 | spec: 14 | type: LoadBalancer 15 | loadBalancerSourceRanges: {{ LOADBALANCER_SOURCE_RANGES }} 16 | target: 17 | group: viya.sas.com 18 | kind: CASDeployment 19 | # This applies to one particular named CAS server: 20 | name: {{ NAME-OF-SERVER }} 21 | version: v1alpha1 22 | -------------------------------------------------------------------------------- /roles/multi-tenancy/templates/cas-manage-cpu-and-memory.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: cas-manage-cpu-and-memory 6 | patch: |- 7 | - op: add 8 | path: /spec/controllerTemplate/spec/containers/0/resources/limits 9 | value: 10 | memory: {{ AMOUNT-OF-RAM }} 11 | - op: replace 12 | path: /spec/controllerTemplate/spec/containers/0/resources/requests/memory 13 | value: 14 | {{ AMOUNT-OF-RAM }} 15 | - op: add 16 | path: /spec/controllerTemplate/spec/containers/0/resources/limits/cpu 17 | value: 18 | {{ NUMBER-OF-CORES }} 19 | - op: replace 20 | path: /spec/controllerTemplate/spec/containers/0/resources/requests/cpu 21 | value: 22 | {{ NUMBER-OF-CORES }} 23 | target: 24 | group: viya.sas.com 25 | kind: CASDeployment 26 | # This applies to one particular named CAS server: 27 | name: {{ NAME-OF-SERVER }} 28 | version: v1alpha1 29 | -------------------------------------------------------------------------------- /roles/orchestration-common/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | V4_CFG_CR_USER: null 6 | V4_CFG_CR_PASSWORD: null 7 | V4_CFG_CR_URL: https://cr.sas.com 8 | V4_CFG_CR_HOST: '{{ V4_CFG_CR_URL | regex_replace("^https?:\/\/(.*)\/?", "\1") }}' 9 | -------------------------------------------------------------------------------- /roles/vdm/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | PROVIDER: custom # [azure|aws|gcp|custom] 6 | NAMESPACE: null 7 | CLUSTER_NAME: null 8 | DEPLOY: true 9 | 10 | V4_CFG_CERTS: null 11 | V4_CFG_LICENSE: null 12 | V4_CFG_DEPLOYMENT_ASSETS: null 13 | V4_CFG_ORDER_NUMBER: null 14 | V4_CFG_CADENCE_NAME: lts 15 | V4_CFG_CADENCE_VERSION: "2022.09" 16 | 17 | V4_CFG_CR_USER: null 18 | V4_CFG_CR_PASSWORD: null 19 | V4_CFG_CR_URL: https://cr.sas.com 20 | V4_CFG_CR_HOST: '{{ V4_CFG_CR_URL | regex_replace("^https?:\/\/(.*)\/?", "\1") }}' 21 | 22 | V4_CFG_SAS_API_KEY: null 23 | V4_CFG_SAS_API_SECRET: null 24 | 25 | V4_CFG_RWX_FILESTORE_ENDPOINT: null 26 | V4_CFG_RWX_FILESTORE_PATH: /export 27 | V4_CFG_RWX_FILESTORE_DATA_PATH: "{{ V4_CFG_RWX_FILESTORE_PATH | replace('/$', '') }}/{{ NAMESPACE }}/data" 28 | V4_CFG_RWX_FILESTORE_HOMES_PATH: "{{ V4_CFG_RWX_FILESTORE_PATH | replace('/$', '') }}/{{ NAMESPACE }}/homes" 29 | # The two variables below are not used in updating any template files or used in any ansible tasks 30 | # They have been removed from CONFIG-VARS.md, if they are used in the future add them back. 31 | V4_CFG_RWX_FILESTORE_ASTORES_PATH: "{{ V4_CFG_RWX_FILESTORE_PATH | replace('/$', '') }}/{{ NAMESPACE }}/astores" 32 | V4_CFG_RWX_FILESTORE_BIN_PATH: "{{ V4_CFG_RWX_FILESTORE_PATH | replace('/$', '') }}/{{ NAMESPACE }}/bin" 33 | 34 | V4_CFG_STORAGECLASS: sas 35 | V4_CFG_RABBITMQ_STORAGECLASS: "{{ 'io2-vol-mq' if PROVIDER == 'aws' else ('managed-csi-premium-v2-mq' if PROVIDER == 'azure' else V4_CFG_STORAGECLASS) }}" 36 | V4_CFG_CRUNCHY_STORAGECLASS: "{{ 'io2-vol-pg' if PROVIDER == 'aws' else ('managed-csi-premium-v2-pg' if PROVIDER == 'azure' else 'pg-storage') }}" 37 | V4_CFG_MANAGE_STORAGE: true 38 | 39 | V4_CFG_DEPLOYMENT_URL_PREFIX: null 40 | V4_CFG_DEPLOYMENT_URL_PORT: null 41 | V4_CFG_INGRESS_FQDN: null 42 | V4_CFG_INGRESS_TYPE: ingress 43 | 44 | V4_CFG_TLS_MODE: front-door # other valid values are full-stack, ingress-only, and disabled 45 | V4_CFG_TLS_CERT: null 46 | V4_CFG_TLS_KEY: null 47 | V4_CFG_TLS_TRUSTED_CA_CERTS: null 48 | V4_CFG_TLS_GENERATOR: openssl # [cert-manager,openssl] 49 | 50 | V4_CFG_CONSUL_ENABLE_LOADBALANCER: false 51 | V4_CFG_EMBEDDED_LDAP_ENABLE: false 52 | V4_CFG_SSSD: null 53 | V4_CFG_SITEDEFAULT: "{{ 'files/sitedefault.yaml' if not V4MT_ENABLE else 'files/sitedefault-mt.yaml' }}" 54 | 55 | V4_CFG_CAS_RAM: null 56 | V4_CFG_CAS_CORES: null 57 | V4_CFG_CAS_WORKER_COUNT: 1 58 | V4_CFG_CAS_ENABLE_LOADBALANCER: false 59 | V4_CFG_CAS_ENABLE_BACKUP_CONTROLLER: false 60 | V4_CFG_CAS_ENABLE_AUTO_RESTART: true 61 | V4_CFG_CONNECT_ENABLE_LOADBALANCER: false 62 | V4_CFG_CONNECT_FQDN: null 63 | V4_CFG_CLUSTER_NODE_POOL_MODE: standard 64 | 65 | V4_CFG_VIYA_STOP_SCHEDULE: null 66 | V4_CFG_VIYA_START_SCHEDULE: null 67 | 68 | # In theory the issuer name can be changed; however, there are a few overlays where this value is hard coded. See: 69 | # - $deploy/sas-bases/overlays/cert-manager-issuer/resources.yaml 70 | # - $deploy/sas-bases/overlays/network/ingress/security/generators/backend-tls-generators.yaml 71 | # - $deploy/sas-bases/overlays/network/istio/security/generators/truststore-only-tls-generators.yaml 72 | # therefore, we will not document this variable. 73 | V4_CFG_CM_ISSUER_NAME: sas-viya-issuer 74 | 75 | V4_CFG_CM_CERTIFICATE_DURATION: 17531 76 | V4_CFG_CM_CERTIFICATE_ADDITIONAL_SAN_DNS: "" 77 | V4_CFG_CM_CERTIFICATE_ADDITIONAL_SAN_IP: "" 78 | 79 | V4_CFG_TLS_DURATION: "{{ V4_CFG_CM_CERTIFICATE_DURATION }}" 80 | V4_CFG_TLS_ADDITIONAL_SAN_DNS: "{{ V4_CFG_CM_CERTIFICATE_ADDITIONAL_SAN_DNS }}" 81 | V4_CFG_TLS_ADDITIONAL_SAN_IP: "{{ V4_CFG_CM_CERTIFICATE_ADDITIONAL_SAN_IP }}" 82 | 83 | V4_ORDERS_CLI_VERSION: 1.1.0 84 | 85 | V4_CFG_ELASTICSEARCH_ENABLE: true 86 | 87 | ## Cloud 88 | V4_CFG_CLOUD_SERVICE_ACCOUNT_NAME: null 89 | V4_CFG_CLOUD_SERVICE_ACCOUNT_AUTH: null 90 | 91 | # Multi-Tenant 92 | V4MT_ENABLE: false 93 | # SAS Viya supports two modes of data isolation (schemaPerApplicationTenant and databasePerTenant) for tenant data. 94 | # Set V4MT_MODE to either schema or database 95 | V4MT_MODE: schema 96 | 97 | V4MT_TENANT_IDS: null 98 | 99 | internal_postgres: false 100 | 101 | # Deployment Operator 102 | V4_DEPLOYMENT_OPERATOR_ENABLED: true 103 | V4_DEPLOYMENT_OPERATOR_SCOPE: cluster 104 | V4_DEPLOYMENT_OPERATOR_NAMESPACE: sasoperator 105 | V4_DEPLOYMENT_OPERATOR_CRB: sasoperator 106 | 107 | ## Below the line deployment -- internal use only 108 | ## Setting true enables using custom du for below the line testing 109 | V4_CFG_BELOW_THE_LINE: false 110 | 111 | ## SAS Workload Orchestrator 112 | V4_WORKLOAD_ORCHESTRATOR_ENABLED: true 113 | 114 | ## NIST Features 115 | V4_CFG_NIST_FEATURES_ENABLED: false 116 | -------------------------------------------------------------------------------- /roles/vdm/files/sitedefault-mt.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | cacerts: 6 | config: 7 | application: 8 | sas.identities.providers.ldap.connection: 9 | host: ldap-svc 10 | password: Password123 11 | port: 389 12 | url: ldap://${sas.identities.providers.ldap.connection.host}:${sas.identities.providers.ldap.connection.port} 13 | userDN: cn=admin,dc=example,dc=com 14 | sas.identities.providers.ldap.group: 15 | baseDN: dc=example,dc=com 16 | accountId: cn 17 | member: uniqueMember 18 | memberOf: memberOf 19 | objectClass: groupOfUniqueNames 20 | objectFilter: (objectClass=groupOfUniqueNames) 21 | searchFilter: cn={0} 22 | sas.identities.providers.ldap.user: 23 | baseDN: dc=example,dc=com 24 | accountId: uid 25 | memberOf: memberOf 26 | objectClass: inetOrgPerson 27 | objectFilter: (objectClass=inetOrgPerson) 28 | searchFilter: ${sas.identities.providers.ldap.user.accountId}={0} 29 | sas.identities.providers.ldap.tenancy.userRdn: ou=people 30 | sas.logon.initial.password: Password123 31 | sas.identities: 32 | administrator: viya_admin 33 | cache.enabled: false 34 | -------------------------------------------------------------------------------- /roles/vdm/files/sitedefault.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | cacerts: 6 | config: 7 | application: 8 | sas.identities.providers.ldap.connection: 9 | host: ldap-svc 10 | password: Password123 11 | port: 389 12 | url: ldap://${sas.identities.providers.ldap.connection.host}:${sas.identities.providers.ldap.connection.port} 13 | userDN: cn=admin,dc=example,dc=com 14 | sas.identities.providers.ldap.group: 15 | baseDN: ou=groups,dc=example,dc=com 16 | accountId: cn 17 | member: uniqueMember 18 | memberOf: memberOf 19 | objectClass: groupOfUniqueNames 20 | objectFilter: (objectClass=groupOfUniqueNames) 21 | searchFilter: cn={0} 22 | sas.identities.providers.ldap.user: 23 | baseDN: ou=people,dc=example,dc=com 24 | accountId: uid 25 | memberOf: memberOf 26 | objectClass: inetOrgPerson 27 | objectFilter: (objectClass=inetOrgPerson) 28 | searchFilter: uid={0} 29 | sas.logon.initial.password: Password123 30 | config/identities/sas.identities/administrator: viya_admin 31 | -------------------------------------------------------------------------------- /roles/vdm/library/overlay_facts.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | from ansible.module_utils.basic import AnsibleModule 6 | from packaging.version import parse as parse_version 7 | import os 8 | 9 | 10 | def main(): 11 | module_args = { 12 | "add": {"default": [], "type": list}, 13 | "existing": {"required": True, "type": dict}, 14 | "cadence_number": {"default": "0.0.0", "type": str}, 15 | "cadence_name": {"default": "lts", "type": str}, 16 | } 17 | 18 | results = dict( 19 | changed=False, 20 | ansible_facts=dict(), 21 | result=dict() 22 | ) 23 | 24 | module = AnsibleModule( 25 | argument_spec=module_args, 26 | supports_check_mode=True 27 | ) 28 | 29 | if module.check_mode: 30 | module.exit_json(**results) 31 | 32 | try: 33 | if len(module.params['add']) > 0: 34 | for overlay in module.params['add']: 35 | 36 | # Version checks 37 | minVersion = parse_version(str(overlay.setdefault("min", "0.0.0"))) 38 | if "max" in overlay and module.params["cadence_name"].lower() == "fast": 39 | continue 40 | maxVersion = parse_version(str(overlay.setdefault("max", "9999.9999.9999"))) 41 | existingVersion = parse_version(module.params['cadence_number']) 42 | if ((existingVersion < minVersion) and module.params["cadence_name"].lower() != "fast") or (existingVersion > maxVersion): 43 | continue 44 | 45 | priority = str(overlay.setdefault("priority", 1)) 46 | phase = "pre" if int(priority) < 50 else "post" 47 | overlay.pop("priority", None) 48 | overlay_type = list(overlay.keys())[0] 49 | 50 | # set correct path for vdm or sas-bases patches 51 | folderPath = os.path.join("site-config/vdm", overlay_type) if bool(overlay.setdefault("vdm", False)) else "sas-bases/" 52 | overlay_path = os.path.join(folderPath, overlay[overlay_type]) 53 | 54 | module.params['existing'].setdefault(overlay_type, {}) 55 | module.params['existing'][overlay_type].setdefault(phase, {}) 56 | 57 | if priority in module.params['existing'][overlay_type][phase]: 58 | if overlay_path not in module.params['existing'][overlay_type][phase][priority]: 59 | module.params['existing'][overlay_type][phase][priority].append(overlay_path) 60 | else: 61 | module.params['existing'][overlay_type][phase].update({priority: [overlay_path]}) 62 | 63 | results['ansible_facts'] = {"vdm_overlays": module.params['existing']} 64 | module.exit_json(**results) 65 | else: 66 | for resource_type, phases in module.params['existing'].items(): 67 | results['result'][resource_type] = {} 68 | for phase in phases: 69 | results['result'][resource_type][phase] = [] 70 | for priority in sorted(module.params['existing'][resource_type][phase]): 71 | results['result'][resource_type][phase] += module.params['existing'][resource_type][phase][priority] 72 | module.exit_json(**results) 73 | except Exception as e: 74 | module.fail_json(error=e, msg="Error occurred") 75 | raise 76 | 77 | 78 | if __name__ == '__main__': 79 | main() 80 | -------------------------------------------------------------------------------- /roles/vdm/tasks/cas.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the CAS server deployment tasks for the vdm role. 6 | # It is included from main.yaml to manage CAS server deployment. 7 | 8 | # Add overlay for CAS server base resources 9 | - name: CAS - base 10 | overlay_facts: 11 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 12 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 13 | existing: "{{ vdm_overlays }}" 14 | add: 15 | - { resources: overlays/cas-server } 16 | tags: 17 | - install 18 | - uninstall 19 | - update 20 | 21 | # If user provides SSSD config, create the directory, copy the file, and add overlays 22 | - name: CAS - user defined sssd 23 | when: 24 | # Only run if SSSD config is provided 25 | - V4_CFG_SSSD is not none 26 | tags: 27 | - install 28 | - uninstall 29 | - update 30 | block: 31 | # Create the cas-server site-config directory 32 | - name: CAS - create cas-server site-config folder 33 | file: 34 | path: "{{ DEPLOY_DIR }}/site-config/cas-server/" 35 | state: directory 36 | mode: "0770" 37 | # Copy the SSSD configuration file 38 | - name: CAS - copy sssd configuration file 39 | copy: 40 | src: "{{ V4_CFG_SSSD }}" 41 | dest: "{{ DEPLOY_DIR }}/site-config/cas-server/sssd.conf" 42 | mode: "0660" 43 | # Add overlays for SSSD sidecar and config 44 | - name: CAS - update sssd kustomizations 45 | overlay_facts: 46 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 47 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 48 | existing: "{{ vdm_overlays }}" 49 | add: 50 | - { transformers: overlays/cas-server/cas-sssd-sidecar.yaml, priority: 0 } 51 | - { transformers: cas-sssd.yaml, vdm: true } 52 | - { generators: sas-sssd-config.yaml, vdm: true } 53 | 54 | # Add overlay for CAS backup controller if enabled 55 | - name: CAS - backup controller 56 | overlay_facts: 57 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 58 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 59 | existing: "{{ vdm_overlays }}" 60 | add: 61 | - { transformers: cas-manage-backup.yaml, vdm: true } 62 | when: 63 | # Only run if backup controller is enabled 64 | - V4_CFG_CAS_ENABLE_BACKUP_CONTROLLER 65 | tags: 66 | - install 67 | - uninstall 68 | - update 69 | 70 | # Add overlays for automatic resource management if RAM or cores are not set 71 | - name: CAS - auto resources 72 | overlay_facts: 73 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 74 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 75 | existing: "{{ vdm_overlays }}" 76 | add: 77 | - { resources: overlays/cas-server/auto-resources, priority: 40 } 78 | - { transformers: overlays/cas-server/auto-resources/remove-resources.yaml, priority: 90 } 79 | when: 80 | # Only run if RAM or cores are not set 81 | - V4_CFG_CAS_RAM is none or V4_CFG_CAS_CORES is none 82 | tags: 83 | - install 84 | - uninstall 85 | - update 86 | 87 | # Add overlay for user-defined CAS resources if RAM and cores are set 88 | - name: CAS - user-defined resources 89 | overlay_facts: 90 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 91 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 92 | existing: "{{ vdm_overlays }}" 93 | add: 94 | - { transformers: cas-manage-cpu-and-memory.yaml, vdm: true } 95 | when: 96 | # Only run if both RAM and cores are set 97 | - V4_CFG_CAS_RAM is not none 98 | - V4_CFG_CAS_CORES is not none 99 | tags: 100 | - install 101 | - uninstall 102 | - update 103 | 104 | # Add overlay for MPP workers if worker count is greater than 1 105 | - name: CAS - MPP workers 106 | overlay_facts: 107 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 108 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 109 | existing: "{{ vdm_overlays }}" 110 | add: 111 | - { transformers: cas-manage-workers.yaml, vdm: true } 112 | when: 113 | # Only run if worker count is greater than 1 114 | - V4_CFG_CAS_WORKER_COUNT |int > 1 115 | tags: 116 | - install 117 | - uninstall 118 | - update 119 | 120 | - name: CAS - External services 121 | overlay_facts: 122 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 123 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 124 | existing: "{{ vdm_overlays }}" 125 | add: 126 | - { transformers: cas-enable-external-services.yaml, vdm: true } 127 | when: 128 | - V4_CFG_CAS_ENABLE_LOADBALANCER 129 | tags: 130 | - install 131 | - uninstall 132 | - update 133 | 134 | - name: CAS - Enable CAS Auto-Restart After Updates 135 | overlay_facts: 136 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 137 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 138 | existing: "{{ vdm_overlays }}" 139 | add: 140 | - { transformers: cas-auto-restart.yaml, vdm: true, min: "2021.2" } 141 | when: 142 | - V4_DEPLOYMENT_OPERATOR_ENABLED 143 | - V4_CFG_CAS_ENABLE_AUTO_RESTART 144 | tags: 145 | - install 146 | - uninstall 147 | - update 148 | -------------------------------------------------------------------------------- /roles/vdm/tasks/connect.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the Connect server deployment tasks for the vdm role. 6 | # It is included from main.yaml to manage Connect server deployment. 7 | 8 | # Add overlay for enabling load balancer for SAS/CONNECT spawner if enabled 9 | - name: Connect - Loadbalancer 10 | overlay_facts: 11 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 12 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 13 | existing: "{{ vdm_overlays }}" 14 | add: 15 | - { resources: sas-connect-spawner-enable-loadbalancer.yaml, vdm: true } 16 | when: 17 | # Only run if load balancer is enabled 18 | - V4_CFG_CONNECT_ENABLE_LOADBALANCER 19 | tags: 20 | - install 21 | - uninstall 22 | - update 23 | 24 | # Add the SAS/CONNECT FQDN to the SAN DNS list for cert-manager if defined 25 | - name: Connect - SAS/CONNECT FQDN to the SAN DNS list for cert-manager 26 | set_fact: 27 | V4_CFG_TLS_ADDITIONAL_SAN_DNS: "{{ V4_CFG_TLS_ADDITIONAL_SAN_DNS }} {{ V4_CFG_CONNECT_FQDN }}" 28 | when: 29 | # Only run if the FQDN is defined 30 | - V4_CFG_CONNECT_FQDN is not none 31 | tags: 32 | - install 33 | - uninstall 34 | - update 35 | -------------------------------------------------------------------------------- /roles/vdm/tasks/copy_overlay.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the overlay copy tasks for the vdm role. 6 | # It is included from main.yaml to manage copying overlay files. 7 | 8 | # Create the VDM resource directory if overlays are present 9 | - name: Copy - create VDM {{ resource }} folder 10 | file: 11 | state: directory 12 | dest: "{{ DEPLOY_DIR }}/site-config/vdm/{{ resource }}" 13 | mode: "0770" 14 | when: overlays|length > 0 15 | tags: 16 | - install 17 | - uninstall 18 | - update 19 | 20 | # Copy each overlay file for the resource using the template module 21 | - name: Copy - VDM {{ resource }} 22 | template: 23 | # Source overlay file 24 | src: "{{ resource }}/{{ overlay | basename }}" 25 | # Destination path for the overlay 26 | dest: "{{ DEPLOY_DIR }}/{{ overlay | dirname }}/{{ overlay | basename | regex_replace('\\..*\\.yaml$', '.yaml') }}" 27 | mode: "0660" 28 | with_items: "{{ overlays }}" 29 | loop_control: 30 | loop_var: overlay 31 | when: "'/vdm/' in overlay" 32 | tags: 33 | - install 34 | - uninstall 35 | - update 36 | -------------------------------------------------------------------------------- /roles/vdm/tasks/elasticsearch.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the Elasticsearch deployment tasks for the vdm role. 6 | # It is included from main.yaml to manage Elasticsearch deployment. 7 | 8 | # Check if the internal-elasticsearch overlays directory exists 9 | - name: Elasticsearch - folder check 10 | stat: 11 | # Path to the internal-elasticsearch overlays directory 12 | path: "{{ DEPLOY_DIR }}/sas-bases/overlays/internal-elasticsearch" 13 | register: result 14 | tags: 15 | - install 16 | - uninstall 17 | - update 18 | 19 | # Add overlays for internal Elasticsearch if enabled and overlays exist 20 | - name: Elasticsearch - add overlays 21 | overlay_facts: 22 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 23 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 24 | existing: "{{ vdm_overlays }}" 25 | add: 26 | - { resources: overlays/internal-elasticsearch } 27 | - { transformers: overlays/internal-elasticsearch/internal-elasticsearch-transformer.yaml } 28 | - { transformers: overlays/internal-elasticsearch/sysctl-transformer.yaml, priority: 55 } 29 | when: 30 | # Only run if Elasticsearch is enabled and overlays exist 31 | - V4_CFG_ELASTICSEARCH_ENABLE 32 | - result.stat.exists 33 | tags: 34 | - install 35 | - uninstall 36 | - update 37 | -------------------------------------------------------------------------------- /roles/vdm/tasks/kustomize.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the kustomize orchestration tasks for the vdm role. 6 | # It is included from main.yaml to manage kustomize overlays and orchestration. 7 | 8 | # Attempt to get the latest git commit hash for build info 9 | - name: Kustomize - not a git repo 10 | command: | 11 | git log -1 --format=format:"%H" 12 | failed_when: 13 | # Only fail if not a git repo and the error is not the expected one 14 | - "'fatal: not a git repository' not in githash.stderr" 15 | - githash.rc != 0 16 | register: githash 17 | tags: 18 | - install 19 | - uninstall 20 | - update 21 | 22 | # Set timestamp and git hash facts for build info 23 | - name: Kustomize - set date and git refspec 24 | set_fact: 25 | # ISO8601 timestamp 26 | timestamp: "{{ ansible_date_time.iso8601 }}" 27 | # Git commit hash or 'unknown' if not available 28 | git_hash: "{{ githash.stdout | default('unknown', -1) }}" 29 | tags: 30 | - install 31 | - uninstall 32 | - update 33 | 34 | # Add buildinfo overlay for kustomize 35 | - name: Kustomize - buildinfo 36 | overlay_facts: 37 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 38 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 39 | existing: "{{ vdm_overlays }}" 40 | add: 41 | - { resources: sas-deployment-buildinfo.yaml, vdm: true } 42 | tags: 43 | - install 44 | - uninstall 45 | - update 46 | 47 | # Gather user customizations from site-config, excluding certain directories 48 | - name: Kustomize - Get user's customizations 49 | siteconfig_info: 50 | path: "{{ DEPLOY_DIR }}" 51 | exclude: 52 | - vdm 53 | - multi-tenant 54 | - sas-tenant-job 55 | - operator-deploy 56 | register: user_customizations 57 | tags: 58 | - install 59 | - uninstall 60 | - update 61 | 62 | # Get the ordered overlays for kustomize 63 | - name: Kustomize - Ordered overlays 64 | overlay_facts: 65 | existing: "{{ vdm_overlays }}" 66 | register: ordered_overlays 67 | tags: 68 | - install 69 | - uninstall 70 | - update 71 | 72 | # Copy overlays for each resource using the copy_overlay.yaml task file 73 | - name: Kustomize - Copy VDM overlays 74 | include_tasks: copy_overlay.yaml 75 | vars: 76 | resource: "{{ item.key }}" 77 | overlays: "{{ item.value.pre | default([], true) + item.value.post | default([], true) }}" 78 | with_dict: "{{ ordered_overlays.result }}" 79 | tags: 80 | - install 81 | - uninstall 82 | - update 83 | 84 | # Generate the kustomization.yaml file from template 85 | - name: Kustomize - Generate kustomization.yaml 86 | template: 87 | src: kustomization.yaml 88 | dest: "{{ DEPLOY_DIR }}/kustomization.yaml" 89 | mode: "0660" 90 | tags: 91 | - install 92 | - uninstall 93 | - update 94 | -------------------------------------------------------------------------------- /roles/vdm/tasks/mirror.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the mirror registry configuration tasks for the vdm role. 6 | # It is included from main.yaml when a non-default container registry is used. 7 | 8 | # Copy the example mirror.yaml to the transformers directory for customization 9 | - name: Mirror - copy example 10 | copy: 11 | # Source example file 12 | src: "{{ DEPLOY_DIR }}/sas-bases/examples/mirror/mirror.yaml" 13 | # Destination for the mirror.yaml template 14 | dest: "{{ role_path }}/templates/transformers/mirror.yaml" 15 | # Set file permissions 16 | mode: "0660" 17 | tags: 18 | - install 19 | - uninstall 20 | - update 21 | 22 | # Replace the MIRROR-HOST placeholder with the configured registry host 23 | - name: Mirror - update example 24 | replace: 25 | # Path to the mirror.yaml file 26 | path: "{{ role_path }}/templates/transformers/mirror.yaml" 27 | # Regex to find the placeholder 28 | regexp: MIRROR-HOST 29 | # Replace with the actual registry host variable 30 | replace: V4_CFG_CR_HOST 31 | tags: 32 | - install 33 | - uninstall 34 | - update 35 | 36 | # Add overlay facts for mirror configuration, supporting different cadence versions 37 | - name: Mirror - overlay 38 | overlay_facts: 39 | # Cadence name and version for overlay selection 40 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 41 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 42 | # Existing overlays to update 43 | existing: "{{ vdm_overlays }}" 44 | # Add overlay and generator entries for mirror support 45 | add: 46 | - { transformers: mirror.yaml, vdm: true, priority: 65 } 47 | - { generators: mirror.yaml, vdm: true, max: "2022.09" } 48 | - { generators: mirror.v2.yaml, vdm: true, min: "2022.10" } 49 | tags: 50 | - install 51 | - uninstall 52 | - update 53 | -------------------------------------------------------------------------------- /roles/vdm/tasks/multi_tenant.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the multi-tenant deployment tasks for the vdm role. 6 | # It is included from main.yaml when multi-tenancy is enabled. 7 | 8 | # Check if the multi-tenant overlays directory exists 9 | - name: Multitenant - folder check 10 | stat: 11 | # Path to the multi-tenant overlays directory 12 | path: "{{ DEPLOY_DIR }}/sas-bases/overlays/multi-tenant" 13 | register: result 14 | tags: 15 | - install 16 | - uninstall 17 | - update 18 | 19 | # Add overlays for multi-tenant support if enabled and overlays exist 20 | - name: Multitenant - add overlays 21 | overlay_facts: 22 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 23 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 24 | existing: "{{ vdm_overlays }}" 25 | add: 26 | - { transformers: overlays/multi-tenant/sas-shared-configmap-transformer.yaml } 27 | when: 28 | # Only run if multi-tenancy is enabled and overlays exist 29 | - V4MT_ENABLE 30 | - result.stat.exists 31 | tags: 32 | - install 33 | - uninstall 34 | - update 35 | 36 | # Create the site-config/multi-tenant directory if multi-tenancy is enabled 37 | - name: Create site-config/multi-tenant folder 38 | file: 39 | state: directory 40 | dest: "{{ DEPLOY_DIR }}/site-config/multi-tenant" 41 | mode: "0770" 42 | when: V4MT_ENABLE 43 | tags: 44 | - install 45 | - uninstall 46 | - update 47 | 48 | # Copy the example sasdefault.yaml for multi-tenant configuration 49 | - name: Copy - site-config/multi-tenant/sasdefault.yaml 50 | template: 51 | src: "{{ DEPLOY_DIR }}/sas-bases/examples/multi-tenant/sasdefault.yaml" 52 | dest: "{{ DEPLOY_DIR }}/site-config/multi-tenant" 53 | mode: "0660" 54 | when: V4MT_ENABLE 55 | tags: 56 | - install 57 | - uninstall 58 | - update 59 | 60 | # Update the INGRESS_HOST placeholder in sasdefault.yaml 61 | - name: Sasdefault - update host 62 | replace: 63 | path: "{{ DEPLOY_DIR }}/site-config/multi-tenant/sasdefault.yaml" 64 | regexp: "{INGRESS_HOST}" 65 | replace: "{{ V4_CFG_INGRESS_FQDN }}" 66 | tags: 67 | - install 68 | - uninstall 69 | - update 70 | 71 | # Uncomment the db-mode line if database-per-tenant mode is enabled 72 | - name: Db mode - uncomment db-mode 73 | replace: 74 | path: "{{ DEPLOY_DIR }}/site-config/multi-tenant/sasdefault.yaml" 75 | regexp: "#\\s*sas.multi.tenancy.db.mode.*$" 76 | replace: " sas.multi.tenancy.db.mode: databasePerTenant" 77 | when: V4MT_MODE|lower == "database" 78 | tags: 79 | - install 80 | - uninstall 81 | - update 82 | -------------------------------------------------------------------------------- /roles/vdm/tasks/postgres/gcp-cloud-sql-proxy.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | - name: Postgres - update cloud-sql-proxy fqdn 6 | tags: 7 | - install 8 | - uninstall 9 | - update 10 | block: 11 | # Update the FQDN for the cloud-sql-proxy in the postgres servers map 12 | - name: Postgres - update cloud-sql-proxy fqdn 13 | ansible.utils.update_fact: 14 | updates: 15 | - path: V4_CFG_POSTGRES_SERVERS[{{ role }}][fqdn] 16 | value: sql-proxy-{{ role }} 17 | register: updated 18 | # Set the updated postgres servers map as a fact 19 | - name: Postgres - update postgres servers map 20 | set_fact: 21 | V4_CFG_POSTGRES_SERVERS: "{{ updated.V4_CFG_POSTGRES_SERVERS }}" 22 | 23 | # Activate the GCP service account and bind IAM policy for the SQL proxy 24 | - name: Postgres - setup cloud-sql-proxy account 25 | shell: | 26 | gcloud auth activate-service-account '{{ V4_CFG_CLOUD_SERVICE_ACCOUNT_NAME }}' --key-file={{ V4_CFG_CLOUD_SERVICE_ACCOUNT_AUTH }} 27 | gcloud iam service-accounts add-iam-policy-binding '{{ settings.service_account }}' --role='roles/iam.workloadIdentityUser' --member='serviceAccount:{{ PROVIDER_ACCOUNT }}.svc.id.goog[{{ NAMESPACE }}/sql-proxy-{{ role }}]' --project='{{ PROVIDER_ACCOUNT }}' 28 | tags: 29 | - install 30 | - uninstall 31 | - update 32 | 33 | - name: Postgres - cloud-sql-proxy overlays 34 | tags: 35 | - install 36 | - uninstall 37 | - update 38 | block: 39 | # Create a cloud-sql-proxy instance YAML from template for this role 40 | - name: Postgres - create cloud-sql-proxy role instance from template 41 | template: 42 | src: "{{ role_path }}/templates/resources/cloud-sql-proxy-instance.yaml" 43 | dest: "{{ role_path }}/templates/resources/cloud-sql-proxy-{{ role }}-instance.yaml" 44 | mode: "0660" 45 | # Add overlays for GCP TLS and proxy configuration 46 | - name: Postgres - add gcp tls overlays 47 | overlay_facts: 48 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 49 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 50 | existing: "{{ vdm_overlays }}" 51 | add: 52 | - { resources: "cloud-sql-proxy-{{ role }}-instance.yaml", vdm: true } 53 | - { transformers: overlays/external-postgres/googlecloud-full-stack-tls-transformer.yaml, priority: 55, max: "2022.09" } 54 | - { transformers: overlays/postgres/external-postgres/gcp-tls-transformer.yaml, priority: 55, min: "2022.10" } 55 | -------------------------------------------------------------------------------- /roles/vdm/tasks/postgres/pg_config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the Postgres ConfigMap deployment tasks for the vdm role. 6 | # It is included from main.yaml to manage Postgres ConfigMap resources. 7 | 8 | - name: pg_config - Check for storage info ConfigMap # noqa: name[casing] 9 | tags: 10 | - install 11 | - uninstall 12 | block: 13 | # Set a fact to track if the storage info ConfigMap is found 14 | - name: Set facts 15 | set_fact: 16 | dac_crunchy_storage_cm_found: false 17 | # Query the cluster for the dac-crunchy-storage-info ConfigMap 18 | - name: pg_config - Look for ConfigMap # noqa: name[casing] 19 | kubernetes.core.k8s_info: 20 | kubeconfig: "{{ KUBECONFIG }}" 21 | api_version: v1 22 | kind: ConfigMap 23 | name: dac-crunchy-storage-info 24 | namespace: "{{ NAMESPACE }}" 25 | register: cm_info 26 | # If the ConfigMap is found, update the fact 27 | - name: pg_config - set fact that ConfigMap was found # noqa: name[casing] 28 | set_fact: 29 | dac_crunchy_storage_cm_found: true 30 | ignore_errors: true 31 | when: cm_info.resources 32 | # If the ConfigMap is found, notify the user that existing storage values will be used 33 | - name: pg_config - Use previous postgres storage map values # noqa: name[casing] 34 | debug: 35 | msg: 36 | - The previously found values for the postgres server storage class and access mode will be used. 37 | - The values you have in your ansible vars will be ignored because the storage class is already present in your cluster. 38 | when: 39 | - dac_crunchy_storage_cm_found 40 | 41 | # Check for v4 crunchy operator if ConfigMap not found 42 | - name: pg_config - v4 crunchy operator check # noqa: name[casing] 43 | when: 44 | - not dac_crunchy_storage_cm_found 45 | tags: 46 | - install 47 | - update 48 | block: 49 | # Query the cluster for the v4 crunchy postgres operator deployment 50 | - name: pg_config - Find v4 crunchy deployment # noqa: name[casing] 51 | kubernetes.core.k8s_info: 52 | kubeconfig: "{{ KUBECONFIG }}" 53 | kind: Deployment 54 | name: sas-crunchy-data-postgres-operator 55 | namespace: "{{ NAMESPACE }}" 56 | register: deploy 57 | # If the deployment is found, set a fact to indicate it 58 | - name: pg_config - v4 crunchy operator found # noqa: name[casing] 59 | set_fact: 60 | v4_crunchy_found: true 61 | when: 62 | - deploy.resources is defined 63 | - deploy.resources | length != 0 64 | # If the deployment is not found, set a fact to indicate it 65 | - name: pg_config - v4 crunchy operator not found # noqa: name[casing] 66 | set_fact: 67 | v4_crunchy_found: false 68 | when: 69 | - deploy.resources is defined 70 | - deploy.resources | length == 0 71 | -------------------------------------------------------------------------------- /roles/vdm/tasks/sizing.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the sizing configuration tasks for the vdm role. 6 | # It is included from main.yaml to manage sizing overlays and configuration. 7 | 8 | # Add overlays for minimal sizing if the cluster node pool mode is minimal 9 | - name: Sizing - minimal 10 | overlay_facts: 11 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 12 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 13 | existing: "{{ vdm_overlays }}" 14 | add: 15 | - { transformers: overlays/cas-server/require-cas-label.yaml, priority: 90, min: 2021.1.2 } 16 | - { transformers: overlays/scaling/single-replica/transformer.yaml, priority: 90, min: 2021.1.1 } 17 | when: 18 | # Only run if minimal node pool mode is set 19 | - V4_CFG_CLUSTER_NODE_POOL_MODE == "minimal" 20 | tags: 21 | - install 22 | - uninstall 23 | - update 24 | -------------------------------------------------------------------------------- /roles/vdm/tasks/start_stop.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the start/stop orchestration tasks for the vdm role. 6 | # It is included from main.yaml to manage start/stop operations for the deployment. 7 | 8 | # Fail if start/stop scheduling is requested for unsupported cadence versions 9 | - name: Start_stop - validate cadence version 10 | ansible.builtin.fail: 11 | msg: > 12 | The schedule-start-stop.yaml transformer is not supported for cadences 2021.1 and older 13 | 14 | To continue deploying 2021.1 or older remove 'V4_CFG_VIYA_STOP_SCHEDULE' & 'V4_CFG_VIYA_START_SCHEDULE' from your 15 | Ansible vars. Alternatively select a newer 'V4_CFG_CADENCE_VERSION' if you would like to use the schedule-start-stop.yaml transformer 16 | when: 17 | # Only run if scheduling is requested and cadence is too old 18 | - V4_CFG_VIYA_STOP_SCHEDULE is not none or V4_CFG_VIYA_START_SCHEDULE is not none 19 | - V4_CFG_CADENCE_VERSION is version('2021.1', "<=") 20 | - V4_CFG_CADENCE_NAME|lower != "fast" 21 | tags: 22 | - install 23 | - uninstall 24 | - update 25 | 26 | # Add the schedule-start-stop transformer overlay for supported cadence versions 27 | - name: Start_stop - add transformer 28 | overlay_facts: 29 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 30 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 31 | existing: "{{ vdm_overlays }}" 32 | add: 33 | - { transformers: schedule-start-stop.yaml, vdm: true, min: "2021.2", priority: 61 } 34 | when: 35 | # Only run if scheduling is requested 36 | - V4_CFG_VIYA_STOP_SCHEDULE is not none or V4_CFG_VIYA_START_SCHEDULE is not none 37 | tags: 38 | - install 39 | - uninstall 40 | - update 41 | -------------------------------------------------------------------------------- /roles/vdm/tasks/storage.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the storage configuration tasks for the vdm role. 6 | # It is included from main.yaml to manage storage overlays and configuration. 7 | 8 | # Add overlay for storage class configuration 9 | - name: Storage - storageclass 10 | overlay_facts: 11 | # Cadence name and version for overlay selection 12 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 13 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 14 | # Existing overlays to update 15 | existing: "{{ vdm_overlays }}" 16 | # Add storageclass transformer overlay 17 | add: 18 | - { transformers: sas-storageclass.yaml, vdm: true, priority: 49 } 19 | tags: 20 | - install 21 | - uninstall 22 | - update 23 | 24 | # Add overlays for NFS storage if endpoints and paths are defined 25 | - name: Storage - nfs 26 | overlay_facts: 27 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 28 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 29 | existing: "{{ vdm_overlays }}" 30 | add: 31 | - { transformers: cas-add-nfs-mount.yaml, vdm: true } 32 | - { transformers: compute-server-add-nfs-mount.yaml, max: 2021.1.6, vdm: true } 33 | - { transformers: compute-server-add-nfs-mount.v2.yaml, min: "2021.2", vdm: true } 34 | - { transformers: launcher-service-add-nfs.yaml, max: 2021.1.6, vdm: true } 35 | - { transformers: launcher-nfs-mount.yaml, min: "2021.2", vdm: true } 36 | when: 37 | # Only run if both NFS endpoint and path are defined 38 | - V4_CFG_RWX_FILESTORE_ENDPOINT is not none 39 | - V4_CFG_RWX_FILESTORE_PATH is not none 40 | tags: 41 | - install 42 | - uninstall 43 | - update 44 | -------------------------------------------------------------------------------- /roles/vdm/tasks/workload_orchestrator.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | # This file contains the workload orchestrator tasks for the vdm role. 6 | # It is included from main.yaml to manage workload orchestration for the deployment. 7 | 8 | # Add overlay for enabling the SAS Workload Orchestrator if enabled and cadence is recent 9 | - name: Workload Orchestrator - Configure SAS Workload Orchestrator Service Account 10 | overlay_facts: 11 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 12 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 13 | existing: "{{ vdm_overlays }}" 14 | add: 15 | - { resources: overlays/sas-workload-orchestrator, min: "2023.08", vdm: false } 16 | when: 17 | # Only run if workload orchestrator is enabled 18 | - V4_WORKLOAD_ORCHESTRATOR_ENABLED 19 | tags: 20 | - install 21 | - uninstall 22 | - update 23 | 24 | # Add overlays to disable the SAS Workload Orchestrator if not enabled 25 | - name: Workload Orchestrator - Disable the SAS Workload Orchestrator Service 26 | overlay_facts: 27 | cadence_name: "{{ V4_CFG_CADENCE_NAME }}" 28 | cadence_number: "{{ V4_CFG_CADENCE_VERSION }}" 29 | existing: "{{ vdm_overlays }}" 30 | add: 31 | - { transformers: examples/sas-workload-orchestrator/enable-disable/sas-workload-orchestrator-disable-patch-transformer.yaml, min: "2023.08", max: "2024.06", vdm: false } 32 | - { transformers: overlays/sas-workload-orchestrator/enable-disable/sas-workload-orchestrator-disable-patch-transformer.yaml, min: "2024.07", vdm: false } 33 | when: 34 | # Only run if workload orchestrator is not enabled 35 | - not V4_WORKLOAD_ORCHESTRATOR_ENABLED 36 | tags: 37 | - install 38 | - uninstall 39 | - update 40 | 41 | # Remove ClusterRoleBinding and ClusterRole if uninstalling and orchestrator is enabled for recent cadence 42 | - name: Workload Orchestrator - Remove the ClusterRoleBinding and ClusterRole 43 | when: 44 | # Only run if uninstalling, orchestrator is enabled, and cadence is recent 45 | - DEPLOY 46 | - V4_WORKLOAD_ORCHESTRATOR_ENABLED 47 | - V4_CFG_CADENCE_VERSION is version('2023.08', ">=") or V4_CFG_CADENCE_NAME|lower == "fast" 48 | tags: 49 | - uninstall 50 | block: 51 | # Remove the ClusterRoleBinding 52 | - name: Workload Orchestrator - Remove ClusterRoleBinding 53 | kubernetes.core.k8s: 54 | kind: ClusterRoleBinding 55 | name: "sas-workload-orchestrator-{{ NAMESPACE }}" 56 | kubeconfig: "{{ KUBECONFIG }}" 57 | state: absent 58 | # Remove the ClusterRole 59 | - name: Workload Orchestrator - Remove ClusterRole 60 | kubernetes.core.k8s: 61 | kind: ClusterRole 62 | name: "sas-workload-orchestrator" 63 | kubeconfig: "{{ KUBECONFIG }}" 64 | state: absent 65 | -------------------------------------------------------------------------------- /roles/vdm/templates/cr_access.json: -------------------------------------------------------------------------------- 1 | { 2 | "auths": { 3 | "{{ V4_CFG_CR_URL }}": { 4 | "username": "{{ V4_CFG_CR_USER }}", 5 | "password": "{{ V4_CFG_CR_PASSWORD }}", 6 | "auth": "{{ ((V4_CFG_CR_USER|string) + ':' + (V4_CFG_CR_PASSWORD|string)) |b64encode }}" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /roles/vdm/templates/deployment-operator-clusterwide.yaml: -------------------------------------------------------------------------------- 1 | # Information about the active clusterwide SAS Viya Platform Deployment Operator 2 | --- 3 | deployment_operator: 4 | mode: clusterwide 5 | namespace: {{ V4_DEPLOYMENT_OPERATOR_NAMESPACE }} 6 | crb: {{ V4_DEPLOYMENT_OPERATOR_CRB }} 7 | resources: {{ OPERATOR_DEPLOY_DIRECTORY }} 8 | -------------------------------------------------------------------------------- /roles/vdm/templates/deployment_operator_kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - operator-base 3 | {% if secret_generator_required %} 4 | generators: 5 | - site-config/secrets.yaml 6 | {% endif %} 7 | transformers: 8 | {% if required_transformers is defined %} 9 | - site-config/required/transformers.yaml 10 | {% if V4_CFG_CR_HOST != "cr.sas.com" %} 11 | - site-config/mirror.yaml 12 | {% endif %} 13 | - site-config/transformer.yaml 14 | {% else %} 15 | - site-config/transformer.yaml 16 | {% if V4_CFG_CR_HOST != "cr.sas.com" %} 17 | - site-config/mirror.yaml 18 | {% endif %} 19 | {% endif %} 20 | ## Uncomment the following inclusion if you are deploying the 21 | ## operator in clusterwide mode. 22 | {% if V4_DEPLOYMENT_OPERATOR_SCOPE|lower == "cluster" %} 23 | - site-config/cluster-wide-transformer.yaml 24 | {% endif %} 25 | {% if V4_CFG_CR_USER is not none %} 26 | secretGenerator: 27 | - name: site-image-pull-secret 28 | type: kubernetes.io/dockerconfigjson 29 | files: 30 | - .dockerconfigjson=site-config/cr_access.json 31 | patches: 32 | - patch: |- 33 | - op: add 34 | path: /spec/template/spec/imagePullSecrets 35 | value: 36 | - name: site-image-pull-secret 37 | target: 38 | kind: Deployment 39 | name: sas-deployment-operator 40 | {% if image_pull_secret_patch_target == "ServiceAccount" %} 41 | - patch: |- 42 | - op: add 43 | path: /imagePullSecrets 44 | value: 45 | - name: site-image-pull-secret 46 | target: 47 | kind: ServiceAccount 48 | name: sas-deployment-operator 49 | {% endif %} 50 | {% endif %} 51 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/customer-provided-ca-certificates.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: ConfigMapGenerator 3 | metadata: 4 | name: sas-customer-provided-ca-certificates 5 | behavior: merge 6 | files: 7 | {% for cacert in V4_CFG_TLS_TRUSTED_CA_CERT_FILES.files %} 8 | - cacerts{{ loop.index }}.pem={{ cacert.path | regex_replace(DEPLOY_DIR + '/', '') }} 9 | {% endfor %} 10 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/customer-provided-ingress-certificate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: SecretGenerator 4 | metadata: 5 | name: sas-ingress-certificate 6 | files: 7 | - tls.crt=site-config/vdm/security/sas-nginx-ingress.crt 8 | - tls.key=site-config/vdm/security/sas-nginx-ingress.key 9 | type: "kubernetes.io/tls" 10 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/customer-provided-merge-sas-certframe-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: ConfigMapGenerator 3 | metadata: 4 | name: sas-certframe-user-config 5 | behavior: merge 6 | literals: 7 | - SAS_CERTIFICATE_DURATION= 8 | {%- if V4_CFG_TLS_GENERATOR == "cert-manager" %} 9 | {{ V4_CFG_TLS_DURATION }}h 10 | {% else %} 11 | "{{ ((V4_CFG_TLS_DURATION|int)/24)|int }}" 12 | {% endif %} 13 | - SAS_CERTIFICATE_ADDITIONAL_SAN_DNS={{ V4_CFG_TLS_ADDITIONAL_SAN_DNS }} 14 | - SAS_CERTIFICATE_ADDITIONAL_SAN_IP={{ V4_CFG_TLS_ADDITIONAL_SAN_IP }} 15 | {% if V4_CFG_TLS_GENERATOR == "openssl" %} 16 | - SAS_CERTIFICATE_GENERATOR=openssl 17 | {% elif V4_CFG_TLS_GENERATOR == "cert-manager" %} 18 | - SAS_CERTIFICATE_GENERATOR=cert-manager 19 | {% endif -%} 20 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/ingress-input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: ingress-input 6 | behavior: merge 7 | literals: 8 | - INGRESS_HOST={{ V4_CFG_INGRESS_FQDN }} 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/mirror.v2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: input 6 | behavior: merge 7 | literals: 8 | - IMAGE_REGISTRY={{ V4_CFG_CR_HOST }} 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/mirror.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: input 6 | behavior: merge 7 | literals: 8 | - IMAGE_REGISTRY={{ V4_CFG_CR_HOST }} 9 | {% if internal_postgres|bool %} 10 | --- 11 | apiVersion: builtin 12 | kind: ConfigMapGenerator 13 | metadata: 14 | name: ccp-image-location 15 | behavior: merge 16 | literals: 17 | - CCP_IMAGE_REPO={{ V4_CFG_CR_HOST }} 18 | - CCP_IMAGE_PATH={{ V4_CFG_CR_HOST }} 19 | {% endif %} 20 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/openldap-bootstrap-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: openldap-bootstrap-config 6 | literals: 7 | - LDAP_TLS="false" 8 | - LDAP_ADMIN_PASSWORD="Password123" 9 | - LDAP_DOMAIN="example.com" 10 | - LDAP_REMOVE_CONFIG_AFTER_SETUP="false" 11 | - DISABLE_CHOWN="false" 12 | - |- 13 | LDAP_USERS_CONF=dn: uid=viya_admin,ou=people,dc=example,dc=com 14 | changetype: add 15 | objectClass: inetOrgPerson 16 | objectclass: extensibleObject 17 | uid: viya_admin 18 | uidNumber: 2001 19 | gidNumber: 2000 20 | cn: administrator 21 | sn: Admin 22 | homeDirectory: /home/viya_admin 23 | mail: viya_admin@example.com 24 | distinguishedName: uid=viya_admin,ou=people,dc=example,dc=com 25 | displayName: Viya Administrator 26 | userPassword: Password123 27 | 28 | dn: uid=user1,ou=people,dc=example,dc=com 29 | changetype: add 30 | objectClass: inetOrgPerson 31 | objectclass: extensibleObject 32 | uid: user1 33 | uidNumber: 7001 34 | gidNumber: 1000 35 | cn: user1 36 | sn: Tester 37 | distinguishedName: uid=user1,ou=people,dc=example,dc=com 38 | displayName: Test User 1 39 | userPassword: Password123 40 | homeDirectory: /home/user1 41 | mail: user1@example.com 42 | 43 | dn: uid=user2,ou=people,dc=example,dc=com 44 | changetype: add 45 | objectClass: inetOrgPerson 46 | objectclass: extensibleObject 47 | uid: user2 48 | uidNumber: 7002 49 | gidNumber: 1000 50 | cn: user2 51 | sn: Tester 52 | distinguishedName: uid=user2,ou=people,dc=example,dc=com 53 | displayName: Test User 2 54 | userPassword: Password123 55 | homeDirectory: /home/user2 56 | mail: user2@example.com 57 | 58 | dn: cn=users,ou=groups,dc=example,dc=com 59 | changetype: add 60 | objectclass: groupofUniqueNames 61 | objectclass: extensibleObject 62 | gidNumber: 1000 63 | distinguishedName: cn=group1,ou=groups,dc=example,dc=com 64 | uniqueMember:uid=user1,ou=people,dc=example,dc=com 65 | uniqueMember:uid=user2,ou=people,dc=example,dc=com 66 | 67 | dn: cn=admins,ou=groups,dc=example,dc=com 68 | changetype: add 69 | objectclass: groupofUniqueNames 70 | objectclass: extensibleObject 71 | gidNumber: 2000 72 | distinguishedName: cn=admins,ou=groups,dc=example,dc=com 73 | uniqueMember:uid=viya_admin,ou=people,dc=example,dc=com 74 | - |- 75 | LDAP_GROUPS_CONF=dn: ou=people,dc=example,dc=com 76 | changetype: add 77 | objectClass: organizationalUnit 78 | ou: people 79 | 80 | dn: ou=groups,dc=example,dc=com 81 | changetype: add 82 | ou: groups 83 | description: All organizational groups 84 | objectclass: organizationalunit 85 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/openldap-bootstrap-mt-config.yaml: -------------------------------------------------------------------------------- 1 | # List of users and groups present 2 | # provider 3 | # +-- viya_admin 4 | # +-- user1 5 | # +-- user2 6 | 7 | --- 8 | apiVersion: builtin 9 | kind: ConfigMapGenerator 10 | metadata: 11 | name: openldap-bootstrap-config 12 | literals: 13 | - LDAP_TLS="false" 14 | - LDAP_ADMIN_PASSWORD="Password123" 15 | - LDAP_DOMAIN="example.com" 16 | - LDAP_REMOVE_CONFIG_AFTER_SETUP="false" 17 | - DISABLE_CHOWN="false" 18 | - |- 19 | LDAP_USERS_CONF=dn: uid=viya_admin,ou=people,ou=provider,dc=example,dc=com 20 | changetype: add 21 | objectClass: inetOrgPerson 22 | objectclass: extensibleObject 23 | uid: viya_admin 24 | uidNumber: 2001 25 | gidNumber: 2000 26 | cn: administrator 27 | sn: Admin 28 | homeDirectory: /home/viya_admin 29 | mail: viya_admin@example.com 30 | distinguishedName: uid=viya_admin,ou=people,ou=provider,dc=example,dc=com 31 | displayName: Viya Administrator 32 | userPassword: Password123 33 | 34 | dn: uid=user1,ou=people,ou=provider,dc=example,dc=com 35 | changetype: add 36 | objectClass: inetOrgPerson 37 | objectclass: extensibleObject 38 | uid: user1 39 | uidNumber: 7001 40 | gidNumber: 1000 41 | cn: user1 42 | sn: Tester 43 | distinguishedName: uid=user1,ou=people,ou=provider,dc=example,dc=com 44 | displayName: Test User 1 45 | userPassword: Password123 46 | homeDirectory: /home/user1 47 | mail: user1@example.com 48 | 49 | dn: uid=user2,ou=people,ou=provider,dc=example,dc=com 50 | changetype: add 51 | objectClass: inetOrgPerson 52 | objectclass: extensibleObject 53 | uid: user2 54 | uidNumber: 7002 55 | gidNumber: 1000 56 | cn: user2 57 | sn: Tester 58 | distinguishedName: uid=user2,ou=people,ou=provider,dc=example,dc=com 59 | displayName: Test User 2 60 | userPassword: Password123 61 | homeDirectory: /home/user2 62 | mail: user2@example.com 63 | 64 | dn: cn=users,ou=groups,ou=provider,dc=example,dc=com 65 | changetype: add 66 | objectclass: groupofUniqueNames 67 | objectclass: extensibleObject 68 | gidNumber: 1000 69 | distinguishedName: cn=group1,ou=groups,ou=provider,dc=example,dc=com 70 | uniqueMember:uid=user1,ou=people,ou=provider,dc=example,dc=com 71 | uniqueMember:uid=user2,ou=people,ou=provider,dc=example,dc=com 72 | 73 | dn: cn=admins,ou=groups,ou=provider,dc=example,dc=com 74 | changetype: add 75 | objectclass: groupofUniqueNames 76 | objectclass: extensibleObject 77 | gidNumber: 2000 78 | distinguishedName: cn=admins,ou=groups,ou=provider,dc=example,dc=com 79 | uniqueMember:uid=viya_admin,ou=people,ou=provider,dc=example,dc=com 80 | - |- 81 | LDAP_GROUPS_CONF=dn: ou=provider,dc=example,dc=com 82 | changetype: add 83 | ou: provider 84 | objectClass: organizationalUnit 85 | objectClass: top 86 | 87 | dn: ou=groups,ou=provider,dc=example,dc=com 88 | changetype: add 89 | ou: groups 90 | description: provider groups 91 | objectClass: organizationalUnit 92 | objectClass: top 93 | 94 | dn: ou=people,ou=provider,dc=example,dc=com 95 | changetype: add 96 | ou: people 97 | objectClass: organizationalUnit 98 | objectClass: top 99 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/postgres-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: postgres-config 6 | literals: 7 | - DATABASE_HOST={{ V4_CFG_POSTGRES_SERVERS.default.fqdn }} 8 | - DATABASE_PORT={{ V4_CFG_POSTGRES_SERVERS.default.server_port }} 9 | - DATABASE_NAME={{ V4_CFG_POSTGRES_DATABASE | default('SharedServices', true) }} 10 | - EXTERNAL_DATABASE="true" 11 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/postgres-sas-user.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | metadata: 4 | name: postgres-sas-user 5 | literals: 6 | - username={{ V4_CFG_POSTGRES_SERVERS.default.admin }} 7 | - password={{ V4_CFG_POSTGRES_SERVERS.default.password }} 8 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/postgres-secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | type: Opaque 4 | behavior: add 5 | metadata: 6 | name: {{ role }}-platform-postgres-user 7 | envs: 8 | - site-config/postgres-{{ role }}-user.env 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-consul-config-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | metadata: 4 | name: sas-consul-config 5 | behavior: merge 6 | literals: 7 | - INGRESS_HOST={{ V4_CFG_INGRESS_FQDN }} 8 | files: 9 | - SITEDEFAULT_CONF=site-config/sitedefault.yaml 10 | {% if V4MT_ENABLE == true %} 11 | - SASDEFAULT_CONF=site-config/multi-tenant/sasdefault.yaml 12 | {% endif %} 13 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-consul-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: ConfigMapGenerator 3 | metadata: 4 | name: sas-consul-config 5 | behavior: merge 6 | files: 7 | - SITEDEFAULT_CONF=site-config/sitedefault.yaml -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-go-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: sas-go-config 6 | behavior: merge 7 | literals: 8 | - SAS_DATABASE_DATABASE={{ V4_CFG_POSTGRES_SERVERS.default.database if 'database' in V4_CFG_POSTGRES_SERVERS.default else 'SharedServices' }} 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-image-pull-secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | metadata: 4 | name: sas-image-pull-secrets 5 | behavior: replace 6 | type: kubernetes.io/dockerconfigjson 7 | files: 8 | - .dockerconfigjson=site-config/cr_access.json 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-license.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | metadata: 4 | name: sas-license 5 | behavior: merge 6 | type: sas.com/license 7 | literals: 8 | - SAS_LICENSE={{ LICENSE_CONTENT }} 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-postgres-config.v2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: sas-postgres-config 6 | behavior: merge 7 | literals: 8 | - DATABASE_HOST={{ V4_CFG_POSTGRES_SERVERS.default.fqdn }} 9 | - DATABASE_PORT={{ V4_CFG_POSTGRES_SERVERS.default.server_port }} 10 | - DATABASE_SSL_ENABLED="{{ V4_CFG_POSTGRES_SERVERS.default.ssl_enforcement_enabled|bool|lower }}" 11 | - DATABASE_NAME={{ V4_CFG_POSTGRES_SERVERS.default.database|default('SharedServices', true) }} 12 | - EXTERNAL_DATABASE="true" 13 | - SAS_DATABASE_DATABASESERVERNAME="postgres" 14 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-postgres-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: sas-postgres-config 6 | behavior: merge 7 | literals: 8 | - DATABASE_HOST={{ V4_CFG_POSTGRES_SERVERS.default.fqdn }} 9 | - DATABASE_PORT={{ V4_CFG_POSTGRES_SERVERS.default.server_port }} 10 | - DATABASE_SSL_ENABLED="false" 11 | - DATABASE_NAME={{ V4_CFG_POSTGRES_SERVERS.default.database|default('SharedServices', true) }} 12 | - EXTERNAL_DATABASE="true" 13 | - SAS_DATABASE_DATABASESERVERNAME="postgres" 14 | - SPRING_DATASOURCE_URL=jdbc:postgresql://{{ V4_CFG_POSTGRES_SERVERS.default.fqdn }}:{{ V4_CFG_POSTGRES_SERVERS.default.port }}/{{ V4_CFG_POSTGRES_SERVERS.default.database if 'database' in V4_CFG_POSTGRES_SERVERS.default else 'SharedServices' }}?currentSchema=${application.schema} 15 | -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-shared-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: ConfigMapGenerator 4 | metadata: 5 | name: sas-shared-config 6 | behavior: merge 7 | literals: 8 | - SAS_SERVICES_URL={{ V4_CFG_DEPLOYMENT_URL_PREFIX }}{{ V4_CFG_INGRESS_FQDN }}{{ V4_CFG_DEPLOYMENT_URL_PORT }} 9 | {% if V4_CFG_CONSUL_ENABLE_LOADBALANCER is defined and V4_CFG_CONSUL_ENABLE_LOADBALANCER %} 10 | - CONSUL_OPTIONS=-client 0.0.0.0 -ui 11 | {% endif %} -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sas-sssd-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | metadata: 4 | name: sas-sssd-config 5 | files: 6 | - SSSD_CONF=site-config/cas-server/sssd.conf 7 | type: Opaque -------------------------------------------------------------------------------- /roles/vdm/templates/generators/sql-proxy-serviceaccountkey.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: SecretGenerator 3 | type: Opaque 4 | behavior: add 5 | metadata: 6 | name: {{ role }}-platform-postgres-user 7 | files: 8 | - site-config/postgres-{{ role }}-user.env 9 | -------------------------------------------------------------------------------- /roles/vdm/templates/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | apiVersion: kustomize.config.k8s.io/v1beta1 3 | 4 | namespace: {{ NAMESPACE }} 5 | 6 | {% for resource in ordered_overlays.result %} 7 | {{ resource }}: 8 | {% if 'pre' in ordered_overlays.result[resource] and ordered_overlays.result[resource]['pre']|length > 0 %} 9 | ## vdm defined {{ resource }} (pre) 10 | {% for overlay in ordered_overlays.result[resource]['pre'] %} 11 | - {{ overlay |dirname }}/{{ overlay | basename | regex_replace('\\..*\\.yaml$', '.yaml') }} 12 | {% endfor %} 13 | {% endif %} 14 | {% if resource in user_customizations.overlays %} 15 | ## user defined {{ resource }} 16 | {% for item in user_customizations.overlays[resource]|sort %} 17 | - {{ item }} 18 | {% endfor %} 19 | {% endif %} 20 | {% if 'post' in ordered_overlays.result[resource] and ordered_overlays.result[resource]['post']|length > 0 %} 21 | ## vdm defined {{ resource }} (post) 22 | {% for overlay in ordered_overlays.result[resource]['post'] %} 23 | - {{ overlay |dirname }}/{{ overlay | basename | regex_replace('\\..*\\.yaml$', '.yaml') }} 24 | {% endfor %} 25 | {% endif %} 26 | 27 | {% endfor %} 28 | {% if "components" not in ordered_overlays.result %} 29 | {% if "components" in user_customizations.overlays %} 30 | components: 31 | ## user defined components 32 | {% for item in user_customizations.overlays['components']|sort %} 33 | - {{ item }} 34 | {% endfor %} 35 | {% endif %} 36 | {% endif %} 37 | -------------------------------------------------------------------------------- /roles/vdm/templates/postgres-user.env: -------------------------------------------------------------------------------- 1 | username={{ settings.admin }} 2 | password={{ settings.password }} 3 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/cloud-sql-proxy-instance.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: sql-proxy-{{ role }} 5 | annotations: 6 | iam.gke.io/gcp-service-account: {{ settings.service_account }} 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: sql-proxy-{{ role }} 12 | labels: 13 | app: sql-proxy-{{ role }} 14 | spec: 15 | replicas: 1 16 | selector: 17 | matchLabels: 18 | app: sql-proxy-{{ role }} 19 | template: 20 | metadata: 21 | labels: 22 | app: sql-proxy-{{ role }} 23 | spec: 24 | containers: 25 | - name: sql-proxy 26 | image: '{{ PROXY_SQL_IMAGE }}' 27 | env: 28 | - name: POSTGRES_CONNECTION_NAME 29 | value: {{ settings.connection_name }} 30 | command: 31 | - "/cloud_sql_proxy" 32 | args: 33 | - "-ip_address_types=PRIVATE" 34 | - "-instances=$(POSTGRES_CONNECTION_NAME)=tcp:0.0.0.0:{{ settings.server_port|default(5432, true) }}" 35 | imagePullSecrets: [] 36 | serviceAccountName: sql-proxy-{{ role }} 37 | --- 38 | kind: Service 39 | apiVersion: v1 40 | metadata: 41 | name: sql-proxy-{{ role }} 42 | labels: 43 | app: sql-proxy-{{ role }} 44 | spec: 45 | ports: 46 | - name: sql 47 | protocol: TCP 48 | port: 5432 49 | targetPort: 5432 50 | selector: 51 | app: sql-proxy-{{ role }} 52 | type: ClusterIP 53 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/consul-ui.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: consul-ui 6 | {% if PROVIDER == "aws" %} 7 | annotations: 8 | service.beta.kubernetes.io/aws-load-balancer-type: nlb 9 | {% endif %} 10 | spec: 11 | type: LoadBalancer 12 | ports: 13 | - name: http 14 | port: 80 15 | protocol: TCP 16 | targetPort: 8500 17 | selector: 18 | app.kubernetes.io/name: sas-consul-server 19 | sas.com/deployment: sas-viya 20 | loadBalancerSourceRanges: {{ LOADBALANCER_SOURCE_RANGES }} 21 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/openldap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: openldap 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: openldap 11 | template: 12 | metadata: 13 | labels: 14 | app: openldap 15 | spec: 16 | hostname: ldap-svc 17 | imagePullSecrets: [] 18 | containers: 19 | - image: "osixia/openldap:1.3.0" 20 | imagePullPolicy: IfNotPresent 21 | name: openldap 22 | ports: 23 | - containerPort: 389 24 | args: 25 | - --copy-service 26 | env: 27 | - name: LDAP_TLS 28 | valueFrom: 29 | configMapKeyRef: 30 | name: openldap-bootstrap-config 31 | key: LDAP_TLS 32 | - name: LDAP_ADMIN_PASSWORD 33 | valueFrom: 34 | configMapKeyRef: 35 | name: openldap-bootstrap-config 36 | key: LDAP_ADMIN_PASSWORD 37 | - name: LDAP_DOMAIN 38 | valueFrom: 39 | configMapKeyRef: 40 | name: openldap-bootstrap-config 41 | key: LDAP_DOMAIN 42 | - name: LDAP_REMOVE_CONFIG_AFTER_SETUP 43 | valueFrom: 44 | configMapKeyRef: 45 | name: openldap-bootstrap-config 46 | key: LDAP_REMOVE_CONFIG_AFTER_SETUP 47 | - name: DISABLE_CHOWN 48 | valueFrom: 49 | configMapKeyRef: 50 | name: openldap-bootstrap-config 51 | key: DISABLE_CHOWN 52 | volumeMounts: 53 | - name: bootstrap-custom 54 | mountPath: "/container/service/slapd/assets/config/bootstrap/ldif/custom" 55 | affinity: 56 | nodeAffinity: 57 | preferredDuringSchedulingIgnoredDuringExecution: 58 | - preference: 59 | matchExpressions: 60 | - key: workload.sas.com/class 61 | operator: In 62 | values: 63 | - stateless 64 | matchFields: [] 65 | weight: 100 66 | - preference: 67 | matchExpressions: 68 | - key: workload.sas.com/class 69 | operator: NotIn 70 | values: 71 | - compute 72 | - cas 73 | - stateful 74 | - connect 75 | matchFields: [] 76 | weight: 50 77 | requiredDuringSchedulingIgnoredDuringExecution: 78 | nodeSelectorTerms: 79 | - matchExpressions: 80 | - key: kubernetes.azure.com/mode 81 | operator: NotIn 82 | values: 83 | - system 84 | matchFields: [] 85 | tolerations: 86 | - effect: NoSchedule 87 | key: workload.sas.com/class 88 | operator: Equal 89 | value: stateful 90 | - effect: NoSchedule 91 | key: workload.sas.com/class 92 | operator: Equal 93 | value: stateless 94 | volumes: 95 | - name: bootstrap-custom 96 | emptyDir: {} 97 | - name: ldap-bootstrap-config 98 | configMap: 99 | name: openldap-bootstrap-config 100 | items: 101 | - key: LDAP_USERS_CONF 102 | path: 07-testUsers.ldif 103 | mode: 0664 104 | - key: LDAP_GROUPS_CONF 105 | path: 06-testGroups.ldif 106 | mode: 0664 107 | initContainers: 108 | - name: ldap-init 109 | image: "osixia/openldap:1.3.0" 110 | command: 111 | - bash 112 | - -c 113 | - "cp -avRL /tmp/ldif/custom/* /container/service/slapd/assets/config/bootstrap/ldif/custom/" 114 | volumeMounts: 115 | - name: bootstrap-custom 116 | mountPath: "/container/service/slapd/assets/config/bootstrap/ldif/custom" 117 | - name: ldap-bootstrap-config 118 | mountPath: "/tmp/ldif/custom" 119 | --- 120 | apiVersion: v1 121 | kind: Service 122 | metadata: 123 | name: ldap-svc 124 | spec: 125 | ports: 126 | - port: 389 127 | protocol: TCP 128 | targetPort: 389 129 | name: ldap 130 | selector: 131 | app: openldap -------------------------------------------------------------------------------- /roles/vdm/templates/resources/openssl-generated-ingress-certificate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | labels: 5 | sas.com/admin: namespace 6 | name: sas-create-openssl-ingress-certificate 7 | spec: 8 | template: 9 | spec: 10 | imagePullSecrets: [] 11 | containers: 12 | - env: 13 | - name: KUBE_POD_NAME 14 | valueFrom: 15 | fieldRef: 16 | apiVersion: v1 17 | fieldPath: metadata.name 18 | # The following lines are optional and should only be set if you want to exclude SAN DNS or IP entries from the ingress controller certificate that are included on back-end server certificates 19 | {% if V4_CFG_TLS_ADDITIONAL_SAN_DNS|length %} 20 | - name: SAS_CERTIFICATE_ADDITIONAL_SAN_DNS 21 | value: "{{ V4_CFG_TLS_ADDITIONAL_SAN_DNS }}" 22 | {% endif %} 23 | {% if V4_CFG_TLS_ADDITIONAL_SAN_IP|length %} 24 | - name: SAS_CERTIFICATE_ADDITIONAL_SAN_IP 25 | value: "{{ V4_CFG_TLS_ADDITIONAL_SAN_IP }}" 26 | {% endif %} 27 | - name: SAS_CERTIFICATE_COMMON_NAME 28 | value: sas-viya-openssl-ingress-certificate 29 | - name: SAS_CERTFRAME_TOKEN_DIR 30 | value: /certframe-token 31 | - name: SAS_CERTIFICATE_SECRET_NAME 32 | value: sas-ingress-certificate 33 | - name: SAS_CERTIFICATE_GENERATOR 34 | value: openssl 35 | - name: SAS_CERTIFICATE_FILE_FORMAT 36 | value: pem 37 | - name: SAS_CERTIFICATE_CA_CERTIFICATE_FILE 38 | value: /security/ca.crt 39 | - name: SAS_CERTIFICATE_FILE 40 | value: /security/tls.crt 41 | - name: SAS_CERTIFICATE_PRIVATE_KEY_FILE 42 | value: /security/tls.key 43 | - name: SAS_CERTIFICATE_EXCLUDE_POD_OWNERREF 44 | value: "true" 45 | envFrom: 46 | - configMapRef: 47 | name: sas-certframe-user-config 48 | image: sas-certframe 49 | imagePullPolicy: IfNotPresent 50 | name: sas-certframe 51 | resources: 52 | limits: 53 | cpu: 500m 54 | memory: 500Mi 55 | requests: 56 | cpu: 50m 57 | memory: 50Mi 58 | securityContext: 59 | allowPrivilegeEscalation: false 60 | capabilities: 61 | drop: 62 | - ALL 63 | privileged: false 64 | readOnlyRootFilesystem: true 65 | volumeMounts: 66 | - mountPath: /certframe-token 67 | name: certframe-token 68 | - mountPath: /security 69 | name: security 70 | restartPolicy: OnFailure 71 | volumes: 72 | - name: certframe-token 73 | secret: 74 | defaultMode: 420 75 | secretName: sas-certframe-token 76 | - emptyDir: {} 77 | name: security 78 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/platform-postgres-dataserver.yaml: -------------------------------------------------------------------------------- 1 | {%- set db = db_default_name_map[role] if ('database' not in settings and role in db_default_name_map) else settings.database|default(role, true) -%} 2 | {%- set server_name = role -%} 3 | apiVersion: webinfdsvr.sas.com/v1beta1 4 | kind: DataServer 5 | metadata: 6 | name: {{ role }}-platform-postgres 7 | annotations: 8 | sas.com/default-database: "false" 9 | spec: 10 | ssl: {{ (settings.ssl_enforcement_enabled if 'ssl_enforcement_enabled' in settings else True)|bool|lower }} 11 | registrations: 12 | - serviceName: {{ role }}-sas-postgres 13 | dataServiceName: {{ role }}-postgres 14 | host: {{ settings.fqdn }} 15 | port: {{ settings.server_port|default(5432, true) }} 16 | users: 17 | - name: dbmsowner 18 | credentials: 19 | input: 20 | secretRef: 21 | name: {{ role }}-platform-postgres-user 22 | usernameKey: username 23 | passwordKey: password 24 | databases: 25 | - name: {{ db }} 26 | --- 27 | apiVersion: v1 28 | kind: Secret 29 | metadata: 30 | name: {{ role }}-platform-postgres-user 31 | labels: 32 | pg-cluster: {{ db }} 33 | stringData: 34 | username: {{ settings.admin }} 35 | password: {{ settings.password }} 36 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/postgres-instance.yaml: -------------------------------------------------------------------------------- 1 | {%- set db = db_default_name_map[role] if ('database' not in settings and role in db_default_name_map) else settings.database|default(role, true) -%} 2 | {%- set server_name = role if role != "default" else "postgres" -%} 3 | apiVersion: webinfdsvr.sas.com/v1 4 | kind: Pgcluster 5 | metadata: 6 | name: {{ server_name }} 7 | annotations: 8 | sas.com/default-database: "{{ (role == "default") | bool|lower}}" 9 | {% if settings.internal|bool %} 10 | sas.com/component-name: sas-crunchy-data-postgres-12 11 | {% endif %} 12 | spec: 13 | internal: {{ settings.internal|bool|lower }} 14 | database: {{ db }} 15 | {% if settings.internal|bool %} 16 | storage: 17 | storageclass: "{{ V4_CFG_STORAGECLASS }}" 18 | {% endif %} 19 | connection: 20 | ssl: {{ (settings.ssl_enforcement_enabled if 'ssl_enforcement_enabled' in settings else True)|bool|lower }} 21 | {% if not settings.internal %} 22 | host: {{ settings.fqdn }} 23 | port: {{ settings.server_port|default(5432, true) }} 24 | rolesecret: postgres-{{ role }}-user 25 | --- 26 | apiVersion: v1 27 | kind: Secret 28 | metadata: 29 | name: postgres-{{ role }}-user 30 | labels: 31 | pg-cluster: "{{ server_name }}" 32 | stringData: 33 | username: {{ settings.admin }} 34 | password: {{ settings.password }} 35 | {% endif %} 36 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/sas-connect-spawner-enable-loadbalancer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: { 5 | {% if PROVIDER == "aws" %} 6 | service.beta.kubernetes.io/aws-load-balancer-type: nlb 7 | {% endif %} 8 | } 9 | name: sas-connect-spawner-loadbalancer 10 | spec: 11 | ports: 12 | - name: service 13 | port: 17551 14 | protocol: TCP 15 | targetPort: service 16 | selector: 17 | app.kubernetes.io/name: sas-connect-spawner 18 | sas.com/deployment: sas-viya 19 | type: LoadBalancer 20 | loadBalancerSourceRanges: {{ LOADBALANCER_SOURCE_RANGES }} 21 | {% if PROVIDER == "azure" -%} 22 | externalTrafficPolicy: Local 23 | {% endif %} 24 | -------------------------------------------------------------------------------- /roles/vdm/templates/resources/sas-deployment-buildinfo.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: sas-deployment-buildinfo 5 | data: 6 | git-hash: "{{ git_hash }}" 7 | timestamp: "{{ timestamp }}" 8 | deployment-tooling: "{{ deployment_tooling }}" -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-add-nfs-mount.yaml: -------------------------------------------------------------------------------- 1 | # Add additional mounts needed to conform to deployment pattern 2 | --- 3 | apiVersion: builtin 4 | kind: PatchTransformer 5 | metadata: 6 | name: cas-add-nfs-mount 7 | patch: |- 8 | - op: add 9 | path: /spec/controllerTemplate/spec/volumes/- 10 | value: 11 | name: cas-admin 12 | - op: add 13 | path: /spec/controllerTemplate/spec/volumes/- 14 | value: 15 | name: nfs-data 16 | nfs: 17 | server: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 18 | path: {{ V4_CFG_RWX_FILESTORE_DATA_PATH }} 19 | - op: add 20 | path: /spec/controllerTemplate/spec/volumes/- 21 | value: 22 | name: nfs-homes 23 | nfs: 24 | server: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 25 | path: {{ V4_CFG_RWX_FILESTORE_HOMES_PATH }} 26 | - op: add 27 | path: /spec/controllerTemplate/spec/containers/0/volumeMounts/- 28 | value: 29 | name: cas-admin 30 | mountPath: /cas/cas-admin 31 | readOnly: true 32 | - op: add 33 | path: /spec/controllerTemplate/spec/containers/0/volumeMounts/- 34 | value: 35 | name: nfs-data 36 | mountPath: /mnt/viya-share/data 37 | - op: add 38 | path: /spec/controllerTemplate/spec/containers/0/volumeMounts/- 39 | value: 40 | name: nfs-homes 41 | mountPath: {{ V4_CFG_RWX_FILESTORE_HOMES_PATH }} 42 | target: 43 | group: viya.sas.com 44 | kind: CASDeployment 45 | name: .* 46 | version: v1alpha1 47 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-auto-restart.yaml: -------------------------------------------------------------------------------- 1 | # This block of code is for setting the automatic restart 2 | # option on a CAS server. Any CAS server with this option 3 | # will automatically restart during updates using the 4 | # Deployment Operator. 5 | --- 6 | apiVersion: builtin 7 | kind: PatchTransformer 8 | metadata: 9 | name: cas-auto-restart 10 | patch: |- 11 | - op: add 12 | path: /spec/autoRestart 13 | value: 14 | true 15 | target: 16 | group: viya.sas.com 17 | kind: CASDeployment 18 | name: .* 19 | version: v1alpha1 20 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-enable-external-services.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: cas-enable-external-services 6 | patch: |- 7 | - op: add 8 | path: /spec/publishBinaryService 9 | value: true 10 | - op: add 11 | path: /spec/serviceTemplate 12 | value: 13 | spec: 14 | type: LoadBalancer 15 | loadBalancerSourceRanges: {{ LOADBALANCER_SOURCE_RANGES }} 16 | {% if PROVIDER == "aws" %} 17 | metadata: 18 | annotations: 19 | service.beta.kubernetes.io/aws-load-balancer-type: nlb 20 | {% endif %} 21 | target: 22 | group: viya.sas.com 23 | kind: CASDeployment 24 | name: .* 25 | # This applies to the default CAS server: 26 | labelSelector: "sas.com/cas-server-default" 27 | version: v1alpha1 28 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-manage-backup.yaml: -------------------------------------------------------------------------------- 1 | # This block of code is for specifying adding a backup controller in an MPP 2 | # deployment. Do not use this block for SMP deployments. 3 | --- 4 | apiVersion: builtin 5 | kind: PatchTransformer 6 | metadata: 7 | name: cas-manage-backup 8 | patch: |- 9 | - op: replace 10 | path: /spec/backupControllers 11 | value: 12 | 1 13 | target: 14 | group: viya.sas.com 15 | kind: CASDeployment 16 | name: .* 17 | # This applies to the default CAS server: 18 | labelSelector: "sas.com/cas-server-default" 19 | version: v1alpha1 20 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-manage-cpu-and-memory.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: cas-manage-cpu-and-memory 6 | patch: |- 7 | - op: add 8 | path: /spec/controllerTemplate/spec/containers/0/resources/limits 9 | value: 10 | memory: {{ V4_CFG_CAS_RAM }} 11 | - op: replace 12 | path: /spec/controllerTemplate/spec/containers/0/resources/requests/memory 13 | value: 14 | {{ V4_CFG_CAS_RAM }} 15 | - op: add 16 | path: /spec/controllerTemplate/spec/containers/0/resources/limits/cpu 17 | value: 18 | {{ V4_CFG_CAS_CORES }} 19 | - op: replace 20 | path: /spec/controllerTemplate/spec/containers/0/resources/requests/cpu 21 | value: 22 | {{ V4_CFG_CAS_CORES }} 23 | target: 24 | group: viya.sas.com 25 | kind: CASDeployment 26 | name: .* 27 | # This applies to the default CAS server: 28 | labelSelector: "sas.com/cas-server-default" 29 | version: v1alpha1 30 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-manage-workers.yaml: -------------------------------------------------------------------------------- 1 | # This block of code is for specifying the number of workers in an MPP 2 | # deployment. Do not use this block for SMP deployments. The default value is 2 3 | --- 4 | apiVersion: builtin 5 | kind: PatchTransformer 6 | metadata: 7 | name: cas-manage-workers 8 | patch: |- 9 | - op: replace 10 | path: /spec/workers 11 | value: 12 | {{ V4_CFG_CAS_WORKER_COUNT }} 13 | target: 14 | group: viya.sas.com 15 | kind: CASDeployment 16 | name: .* 17 | # This applies to the default CAS server: 18 | labelSelector: "sas.com/cas-server-default" 19 | version: v1alpha1 20 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cas-sssd.yaml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Kustomize patch to add external SSSD secret in CAS deployment. 3 | # See README.md for more information. 4 | ############################################################################### 5 | --- 6 | apiVersion: builtin 7 | kind: PatchTransformer 8 | metadata: 9 | name: cas-sssd-example 10 | patch: |- 11 | - op: add 12 | path: /spec/controllerTemplate/spec/volumes/- 13 | value: 14 | name: sssd-config 15 | secret: 16 | secretName: sas-sssd-config 17 | defaultMode: 420 18 | items: 19 | - key: SSSD_CONF 20 | mode: 384 21 | path: sssd.conf 22 | 23 | - op: add 24 | path: /spec/controllerTemplate/spec/containers/3/volumeMounts/- 25 | value: 26 | name: sssd-config 27 | mountPath: /sssd 28 | target: 29 | group: viya.sas.com 30 | kind: CASDeployment 31 | name: .* 32 | version: v1alpha1 33 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/cert-manager-provided-ingress-certificate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: sas-cert-manager-ingress-annotation-transformer 6 | patch: |- 7 | - op: add 8 | path: /metadata/annotations/cert-manager.io~1issuer 9 | value: {{ V4_CFG_CM_ISSUER_NAME }} # name of the cert-manager issuer that will supply the ingress cert 10 | target: 11 | kind: Ingress 12 | name: .* 13 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/compute-server-add-nfs-mount.v2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: compute-server-add-nfs-mount 6 | patch: |- 7 | - op: add 8 | path: /template/spec/volumes/- 9 | value: 10 | name: nfs-data 11 | nfs: 12 | path: {{ V4_CFG_RWX_FILESTORE_DATA_PATH }} 13 | server: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 14 | - op: add 15 | path: /template/spec/containers/0/volumeMounts/- 16 | value: 17 | mountPath: /mnt/viya-share/data 18 | name: nfs-data 19 | target: 20 | kind: PodTemplate 21 | version: v1 22 | labelSelector: sas.com/template-intent=sas-launcher 23 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/compute-server-add-nfs-mount.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: compute-server-add-nfs-mount 6 | patch: |- 7 | - op: add 8 | path: /template/spec/containers/0/volumeMounts/- 9 | value: 10 | mountPath: /mnt/viya-share/data 11 | name: nfs-data 12 | - op: add 13 | path: /template/spec/containers/0/volumeMounts/- 14 | value: 15 | mountPath: /mnt/viya-share/homes 16 | name: nfs-homes 17 | - op: add 18 | path: /template/spec/volumes/- 19 | value: 20 | name: nfs-data 21 | nfs: 22 | server: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 23 | path: {{ V4_CFG_RWX_FILESTORE_DATA_PATH }} 24 | - op: add 25 | path: /template/spec/volumes/- 26 | value: 27 | name: nfs-homes 28 | nfs: 29 | server: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 30 | path: {{ V4_CFG_RWX_FILESTORE_HOMES_PATH }} 31 | target: 32 | kind: PodTemplate 33 | name: sas-compute-job-config 34 | version: v1 -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/crunchy-storage-transformer.yaml: -------------------------------------------------------------------------------- 1 | {%- set sas_crunchy_pg_name = pg_cluster_name_map[role] -%} 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: {{ sas_crunchy_pg_name }}-crunchy-storage-transformer 6 | patch: |- 7 | # This value can be changed but not decreased after the initial deployment 8 | - op: replace 9 | path: /spec/instances/0/dataVolumeClaimSpec/resources/requests 10 | value: 11 | storage: {{ settings.postgres_pvc_storage_size|default('128Gi', true) }} 12 | 13 | # This value can be changed but not decreased after the initial deployment 14 | - op: replace 15 | path: /spec/backups/pgbackrest/repos/0/volume/volumeClaimSpec/resources/requests 16 | value: 17 | storage: {{ settings.backrest_pvc_storage_size|default('128Gi', true) }} 18 | 19 | {% if role == "default" %} 20 | # This value cannot be changed after the initial deployment 21 | - op: replace 22 | path: /spec/instances/0/dataVolumeClaimSpec/accessModes 23 | value: 24 | - {{ default_postgres_pvc_access_mode if (default_postgres_pvc_access_mode is defined) else settings.postgres_pvc_access_mode|default('ReadWriteOnce', true) }} 25 | 26 | # This value cannot be changed after the initial deployment 27 | - op: replace 28 | path: /spec/backups/pgbackrest/repos/0/volume/volumeClaimSpec/accessModes 29 | value: 30 | - {{ default_backrest_pvc_access_mode if (default_backrest_pvc_access_mode is defined) else settings.backrest_pvc_access_mode|default('ReadWriteOnce', true) }} 31 | 32 | # This value cannot be changed after the initial deployment 33 | - op: replace 34 | path: /spec/instances/0/dataVolumeClaimSpec/storageClassName 35 | value: {{ default_postgres_storage_class if (default_postgres_storage_class is defined) else settings.postgres_storage_class|default(V4_CFG_CRUNCHY_STORAGECLASS, true) }} 36 | 37 | # This value cannot be changed after the initial deployment 38 | - op: replace 39 | path: /spec/backups/pgbackrest/repos/0/volume/volumeClaimSpec/storageClassName 40 | value: {{ default_backrest_storage_class if (default_backrest_storage_class is defined) else settings.backrest_storage_class|default(V4_CFG_CRUNCHY_STORAGECLASS, true) }} 41 | 42 | {% elif role == "cds-postgres" %} 43 | # This value cannot be changed after the initial deployment 44 | - op: replace 45 | path: /spec/instances/0/dataVolumeClaimSpec/accessModes 46 | value: 47 | - {{ cds_postgres_pvc_access_mode if (cds_postgres_pvc_access_mode is defined) else settings.postgres_pvc_access_mode|default('ReadWriteOnce', true) }} 48 | 49 | # This value cannot be changed after the initial deployment 50 | - op: replace 51 | path: /spec/backups/pgbackrest/repos/0/volume/volumeClaimSpec/accessModes 52 | value: 53 | - {{ cds_backrest_pvc_access_mode if (cds_backrest_pvc_access_mode is defined) else settings.backrest_pvc_access_mode|default('ReadWriteOnce', true) }} 54 | 55 | # This value cannot be changed after the initial deployment 56 | - op: replace 57 | path: /spec/instances/0/dataVolumeClaimSpec/storageClassName 58 | value: {{ cds_postgres_storage_class if (cds_postgres_storage_class is defined) else settings.postgres_storage_class|default(V4_CFG_CRUNCHY_STORAGECLASS, true) }} 59 | 60 | # This value cannot be changed after the initial deployment 61 | - op: replace 62 | path: /spec/backups/pgbackrest/repos/0/volume/volumeClaimSpec/storageClassName 63 | value: {{ cds_backrest_storage_class if (cds_backrest_storage_class is defined) else settings.backrest_storage_class|default(V4_CFG_CRUNCHY_STORAGECLASS, true) }} 64 | 65 | {% endif %} 66 | target: 67 | group: postgres-operator.crunchydata.com 68 | kind: PostgresCluster 69 | name: {{ sas_crunchy_pg_name }} 70 | version: v1beta1 71 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/dataserver-transformer.yaml: -------------------------------------------------------------------------------- 1 | {%- set db = db_default_name_map[role] if ('database' not in settings and role in db_default_name_map) else settings.database|default(role, true) -%} 2 | {%- set dataserver_name = pg_dataserver_name_map[role] -%} 3 | apiVersion: builtin 4 | kind: PatchTransformer 5 | metadata: 6 | name: {{ dataserver_name }}-dataserver-transformer 7 | patch: |- 8 | - op: add 9 | path: "/metadata/annotations/sas.com~1database-server-location" 10 | value: external # Identifies that database server is external 11 | 12 | - op: replace 13 | path: /spec/databases/0/name 14 | value: {{ db }} 15 | 16 | - op: replace 17 | path: /spec/users/0/credentials/input 18 | value: 19 | secretRef: 20 | name: {{ role }}-platform-postgres-user 21 | usernameKey: username # For internal use, do not modify 22 | passwordKey: password # For internal use, do not modify 23 | 24 | - op: replace 25 | path: /spec/registrations/0/host 26 | value: {{ settings.fqdn }} 27 | 28 | - op: replace 29 | path: /spec/registrations/0/port 30 | value: {{ settings.server_port|default(5432, true) }} 31 | 32 | - op: replace 33 | path: /spec/ssl 34 | value: {{ (settings.ssl_enforcement_enabled if 'ssl_enforcement_enabled' in settings else True)|bool|lower }} 35 | target: 36 | group: webinfdsvr.sas.com 37 | kind: DataServer 38 | version: v1beta1 39 | name: {{ dataserver_name }} 40 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/launcher-nfs-mount.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: sas-launcher-nfs-mount 6 | patch: |- 7 | - op: add 8 | path: /metadata/annotations/launcher.sas.com~1nfs-server 9 | value: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 10 | target: 11 | kind: PodTemplate 12 | labelSelector: sas.com/template-intent=sas-launcher 13 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/launcher-service-add-nfs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: launcher-service-add-nfs 6 | patch: |- 7 | - op: add 8 | path: "/metadata/annotations/launcher.sas.com~1nfs-server" 9 | value: {{ V4_CFG_RWX_FILESTORE_ENDPOINT }} 10 | target: 11 | kind: PodTemplate 12 | name: sas-launcher-job-config 13 | version: v1 -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/nginx-ingressclass.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: add ingress class 6 | patch: |- 7 | - op: add 8 | path: /metadata/annotations/kubernetes.io~1ingress.class 9 | value: nginx 10 | target: 11 | kind: Ingress 12 | --- 13 | apiVersion: builtin 14 | kind: PatchTransformer 15 | metadata: 16 | name: cas add ingress class 17 | patch: |- 18 | - op: add 19 | path: /spec/ingressTemplate/metadata/annotations/kubernetes.io~1ingress.class 20 | value: nginx 21 | target: 22 | group: viya.sas.com 23 | kind: CASDeployment 24 | name: .* 25 | version: v1alpha1 26 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/openldap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: PatchTransformer 3 | metadata: 4 | name: openldap 5 | patch: |- 6 | - op: add 7 | path: /spec/template/spec/imagePullSecrets 8 | value: [] 9 | target: 10 | group: apps 11 | kind: Deployment 12 | name: openldap 13 | version: v1 -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/postgres-storage-transformer.v2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: PatchTransformer 3 | metadata: 4 | name: postgres-storage-transformer 5 | patch: |- 6 | - op: replace 7 | path: /spec/BackrestStorage/storageclass 8 | value: "{{ V4_CFG_STORAGECLASS }}" 9 | - op: replace 10 | path: /spec/BackrestStorage/storagetype 11 | value: dynamic 12 | - op: replace 13 | path: /spec/PrimaryStorage/storageclass 14 | value: "{{ V4_CFG_STORAGECLASS }}" 15 | - op: replace 16 | path: /spec/PrimaryStorage/storagetype 17 | value: dynamic 18 | - op: replace 19 | path: /spec/ReplicaStorage/storageclass 20 | value: "{{ V4_CFG_STORAGECLASS }}" 21 | - op: replace 22 | path: /spec/ReplicaStorage/storagetype 23 | value: dynamic 24 | target: 25 | group: crunchydata.com 26 | kind: Pgcluster 27 | name: .* 28 | version: v1 29 | --- 30 | apiVersion: builtin 31 | kind: PatchTransformer 32 | metadata: 33 | name: replica-postgres-storage-transformer 34 | patch: |- 35 | - op: replace 36 | path: /spec/replicastorage/storageclass 37 | value: "{{ V4_CFG_STORAGECLASS }}" 38 | - op: replace 39 | path: /spec/replicastorage/storagetype 40 | value: dynamic 41 | target: 42 | group: crunchydata.com 43 | kind: Pgreplica 44 | name: .* 45 | version: v1 -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/postgres-storage-transformer.v3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: PatchTransformer 3 | metadata: 4 | name: postgres-storage-transformer 5 | patch: |- 6 | - op: replace 7 | path: /spec/storage/storageclass 8 | value: {{ V4_CFG_STORAGECLASS }} 9 | - op: add 10 | path: /metadata/annotations/sas.com~1crunchy-storage-type 11 | value: dynamic 12 | target: 13 | group: webinfdsvr.sas.com 14 | kind: Pgcluster 15 | name: .* # By default, target all Pgclusters. Change to a specific name to target just one. 16 | version: v1 17 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/postgres-storage-transformer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: builtin 2 | kind: PatchTransformer 3 | metadata: 4 | name: postgres-storage-transformer 5 | patch: |- 6 | - op: replace 7 | path: /spec/ArchiveStorage/storageclass 8 | value: "{{ V4_CFG_STORAGECLASS }}" 9 | - op: replace 10 | path: /spec/ArchiveStorage/storagetype 11 | value: dynamic 12 | - op: replace 13 | path: /spec/BackrestStorage/storageclass 14 | value: "{{ V4_CFG_STORAGECLASS }}" 15 | - op: replace 16 | path: /spec/BackrestStorage/storagetype 17 | value: dynamic 18 | - op: replace 19 | path: /spec/PrimaryStorage/storageclass 20 | value: "{{ V4_CFG_STORAGECLASS }}" 21 | - op: replace 22 | path: /spec/PrimaryStorage/storagetype 23 | value: dynamic 24 | - op: replace 25 | path: /spec/ReplicaStorage/storageclass 26 | value: "{{ V4_CFG_STORAGECLASS }}" 27 | - op: replace 28 | path: /spec/ReplicaStorage/storagetype 29 | value: dynamic 30 | target: 31 | group: crunchydata.com 32 | kind: Pgcluster 33 | name: .* 34 | version: v1 35 | --- 36 | apiVersion: builtin 37 | kind: PatchTransformer 38 | metadata: 39 | name: replica-postgres-storage-transformer 40 | patch: |- 41 | - op: replace 42 | path: /spec/replicastorage/storageclass 43 | value: "{{ V4_CFG_STORAGECLASS }}" 44 | - op: replace 45 | path: /spec/replicastorage/storagetype 46 | value: dynamic 47 | target: 48 | group: crunchydata.com 49 | kind: Pgreplica 50 | name: .* 51 | version: v1 -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/rabbitmq-transformer.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: rabbitmq-transformer-0 6 | patch: |- 7 | - op: replace 8 | path: /spec/template/spec/containers/0/resources/limits/memory 9 | value: 10 | 2Gi 11 | target: 12 | group: apps 13 | name: sas-rabbitmq-server 14 | kind: StatefulSet 15 | version: v1 -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/sas-storageclass.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: sas-pv-storageclass 6 | patch: |- 7 | kind: PersistentStorageClass 8 | metadata: 9 | name: wildcard 10 | spec: 11 | storageClassName: "{{ V4_CFG_STORAGECLASS }}" 12 | target: 13 | kind: PersistentVolumeClaim 14 | --- 15 | apiVersion: builtin 16 | kind: PatchTransformer 17 | metadata: 18 | name: sas-ss-storageclass 19 | patch: |- 20 | - op: add 21 | path: /spec/volumeClaimTemplates/0/spec/storageClassName 22 | value: {{ V4_CFG_STORAGECLASS }} 23 | target: 24 | group: apps 25 | kind: StatefulSet 26 | annotationSelector: sas.com/component-name notin (sas-rabbitmq-server,sas-airflow,sas-risk-cirrus-search,sas-workload-orchestrator,sas-data-agent-server-colocated) 27 | --- 28 | apiVersion: builtin 29 | kind: PatchTransformer 30 | metadata: 31 | name: sas-rabbitmq-storageclass 32 | patch: |- 33 | - op: add 34 | path: /spec/volumeClaimTemplates/0/spec/storageClassName 35 | value: {{ V4_CFG_RABBITMQ_STORAGECLASS }} 36 | - op: replace 37 | path: /spec/volumeClaimTemplates/0/spec/resources/requests/storage 38 | value: 4Gi 39 | target: 40 | group: apps 41 | kind: StatefulSet 42 | annotationSelector: sas.com/component-name in (sas-rabbitmq-server) 43 | -------------------------------------------------------------------------------- /roles/vdm/templates/transformers/schedule-start-stop.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: builtin 3 | kind: PatchTransformer 4 | metadata: 5 | name: schedule-stop-all 6 | patch: |- 7 | - op: replace 8 | path: /spec/schedule 9 | # schedule: MUST BE PROVIDED BY USER. 10 | # This is the cron schedule by which the sas-stop-all job is run. 11 | # Example: 12 | # value: '0 19 * * 1-5' 13 | {% if V4_CFG_VIYA_STOP_SCHEDULE is not none %} 14 | value: {{ V4_CFG_VIYA_STOP_SCHEDULE }} 15 | {% else %} 16 | value: '0 19 * * 1-5' 17 | {% endif %} 18 | - op: replace 19 | path: /spec/suspend 20 | {% if V4_CFG_VIYA_STOP_SCHEDULE is not none %} 21 | value: false 22 | {% else %} 23 | value: true 24 | {% endif %} 25 | - op: replace 26 | path: /metadata/labels/sas.com~1deployment 27 | value: 'user-specified' 28 | target: 29 | name: sas-stop-all 30 | kind: CronJob 31 | --- 32 | apiVersion: builtin 33 | kind: PatchTransformer 34 | metadata: 35 | name: schedule-start-all 36 | patch: |- 37 | - op: replace 38 | path: /spec/schedule 39 | # schedule: MUST BE PROVIDED BY USER. 40 | # This is the cron schedule by which the sas-start-all job is run 41 | # Example: 42 | # value: '0 7 * * 1-5' 43 | {% if V4_CFG_VIYA_START_SCHEDULE is not none %} 44 | value: {{ V4_CFG_VIYA_START_SCHEDULE }} 45 | {% else %} 46 | value: '0 7 * * 1-5' 47 | {% endif %} 48 | - op: replace 49 | path: /spec/suspend 50 | {% if V4_CFG_VIYA_START_SCHEDULE is not none %} 51 | value: false 52 | {% else %} 53 | value: true 54 | {% endif %} 55 | - op: replace 56 | path: /metadata/labels/sas.com~1deployment 57 | value: 'user-specified' 58 | target: 59 | name: sas-start-all 60 | kind: CronJob 61 | -------------------------------------------------------------------------------- /roles/vdm/vars/main.yaml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020-2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | --- 5 | PROXY_SQL_IMAGE: gcr.io/cloudsql-docker/gce-proxy:1.20.2 6 | 7 | vdm_overlays: {} 8 | 9 | db_default_name_map: { 10 | default: SharedServices, 11 | cds-postgres: SharedServices 12 | } 13 | 14 | pg_dataserver_name_map: { 15 | default: sas-platform-postgres, 16 | cds-postgres: sas-cds-postgres 17 | } 18 | 19 | pg_cluster_name_map: { 20 | default: sas-crunchy-platform-postgres, 21 | cds-postgres: sas-crunchy-cds-postgres 22 | } 23 | # TODO - Fix once 2021.1.6 is ready and the kustomization files have been updated 24 | network_name_map: { 25 | ingress: networking.k8s.io, 26 | contour: projectcountour.io, 27 | route: route.openshift.io 28 | } 29 | --------------------------------------------------------------------------------