├── .dockerignore ├── .github ├── pull_request_template.md └── workflows │ ├── ci.yaml │ ├── docker.yaml │ ├── integration_tests.yaml │ ├── patch.yaml │ ├── pypi.yaml │ ├── tests.yaml │ └── transfer_repo_image.yaml ├── .gitignore ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── MAINTAINERS.md ├── MANIFEST.in ├── README.md ├── SECURITY.md ├── bin ├── kubemarine └── kubemarine.cmd ├── ci ├── Dockerfile-transfer ├── default_cluster.yaml └── extended_cluster.yaml ├── documentation ├── Ansible_Breaking_Changes.md ├── Installation.md ├── Kubecheck.md ├── LoadBalancing.md ├── Logging.md ├── Maintenance.md ├── PackageExtension.md ├── Troubleshooting.md ├── design │ ├── 1-upgrade-patches-registration-and-implementation.md │ └── 3-release-notes-management.md ├── images │ ├── all-in-one.png │ ├── full-ha.png │ ├── mini-ha.png │ └── tls-termination-nginx.png └── internal │ ├── Hardening.md │ ├── Kubemarine-docker-building.md │ ├── NetworkPerfomance.md │ ├── Patches.md │ └── Release.md ├── examples ├── cluster.yaml │ ├── allinone-cluster-ol7.yaml │ ├── allinone-cluster.yaml │ ├── full-cluster.yaml │ ├── miniha-cluster.yaml │ ├── minimal-cluster.yaml │ └── typical-cluster.yaml └── procedure.yaml │ ├── full-backup.yaml │ ├── full-reboot.yaml │ ├── full-restore.yaml │ ├── minimal-backup.yaml │ └── minimal-restore.yaml ├── kubemarine.ico ├── kubemarine.spec ├── kubemarine ├── __init__.py ├── __main__.py ├── admission.py ├── apparmor.py ├── apt.py ├── audit.py ├── core │ ├── __init__.py │ ├── action.py │ ├── annotations.py │ ├── cluster.py │ ├── connections.py │ ├── defaults.py │ ├── environment.py │ ├── errors.py │ ├── executor.py │ ├── flow.py │ ├── group.py │ ├── inventory.py │ ├── log.py │ ├── os.py │ ├── patch.py │ ├── proxytypes.py │ ├── resources.py │ ├── schema.py │ ├── static.py │ ├── summary.py │ ├── utils.py │ └── yaml_merger.py ├── coredns.py ├── cri │ ├── __init__.py │ └── containerd.py ├── demo.py ├── etcd.py ├── haproxy.py ├── jinja.py ├── k8s_certs.py ├── keepalived.py ├── kubernetes │ ├── __init__.py │ ├── components.py │ ├── daemonset.py │ ├── deployment.py │ ├── object.py │ ├── replicaset.py │ ├── secrets.py │ └── statefulset.py ├── kubernetes_accounts.py ├── modprobe.py ├── packages.py ├── patches │ ├── __init__.py │ └── software_upgrade.yaml ├── plugins │ ├── __init__.py │ ├── builtin.py │ ├── calico.py │ ├── kubernetes_dashboard.py │ ├── local_path_provisioner.py │ ├── manifest.py │ ├── nginx_ingress.py │ └── yaml │ │ ├── calico-apiserver-v3.24.2-original.yaml │ │ ├── calico-apiserver-v3.25.1-original.yaml │ │ ├── calico-apiserver-v3.26.1-original.yaml │ │ ├── calico-apiserver-v3.26.4-original.yaml │ │ ├── calico-apiserver-v3.27.0-original.yaml │ │ ├── calico-apiserver-v3.27.3-original.yaml │ │ ├── calico-apiserver-v3.27.4-original.yaml │ │ ├── calico-apiserver-v3.28.1-original.yaml │ │ ├── calico-apiserver-v3.29.1-original.yaml │ │ ├── calico-v3.22.2-original.yaml │ │ ├── calico-v3.24.2-original.yaml │ │ ├── calico-v3.25.1-original.yaml │ │ ├── calico-v3.26.1-original.yaml │ │ ├── calico-v3.26.4-original.yaml │ │ ├── calico-v3.27.0-original.yaml │ │ ├── calico-v3.27.3-original.yaml │ │ ├── calico-v3.27.4-original.yaml │ │ ├── calico-v3.28.1-original.yaml │ │ ├── calico-v3.29.1-original.yaml │ │ ├── kubernetes-dashboard-v2.5.1-original.yaml │ │ ├── kubernetes-dashboard-v2.7.0-original.yaml │ │ ├── local-path-provisioner-v0.0.22-original.yaml │ │ ├── local-path-provisioner-v0.0.23-original.yaml │ │ ├── local-path-provisioner-v0.0.24-original.yaml │ │ ├── local-path-provisioner-v0.0.25-original.yaml │ │ ├── local-path-provisioner-v0.0.26-original.yaml │ │ ├── local-path-provisioner-v0.0.27-original.yaml │ │ ├── local-path-provisioner-v0.0.31-original.yaml │ │ ├── nginx-ingress-controller-v1.10.1-original.yaml │ │ ├── nginx-ingress-controller-v1.11.1-original.yaml │ │ ├── nginx-ingress-controller-v1.11.5-original.yaml │ │ ├── nginx-ingress-controller-v1.11.6-original.yaml │ │ ├── nginx-ingress-controller-v1.2.0-original.yaml │ │ ├── nginx-ingress-controller-v1.4.0-original.yaml │ │ ├── nginx-ingress-controller-v1.7.0-original.yaml │ │ ├── nginx-ingress-controller-v1.8.1-original.yaml │ │ ├── nginx-ingress-controller-v1.8.4-original.yaml │ │ ├── nginx-ingress-controller-v1.9.4-original.yaml │ │ ├── nginx-ingress-controller-v1.9.5-original.yaml │ │ └── nginx-ingress-controller-v1.9.6-original.yaml ├── procedures │ ├── __init__.py │ ├── add_node.py │ ├── backup.py │ ├── cert_renew.py │ ├── check_iaas.py │ ├── check_paas.py │ ├── config.py │ ├── do.py │ ├── install.py │ ├── manage_pss.py │ ├── migrate_kubemarine.py │ ├── reboot.py │ ├── reconfigure.py │ ├── remove_node.py │ ├── restore.py │ └── upgrade.py ├── py.typed ├── resources │ ├── __init__.py │ ├── configurations │ │ ├── __init__.py │ │ ├── compatibility │ │ │ ├── internal │ │ │ │ ├── kubernetes_images.yaml │ │ │ │ ├── packages.yaml │ │ │ │ ├── plugins.yaml │ │ │ │ └── thirdparties.yaml │ │ │ └── kubernetes_versions.yaml │ │ ├── defaults.yaml │ │ └── globals.yaml │ ├── drop_ins │ │ ├── __init__.py │ │ ├── haproxy.conf │ │ └── keepalived.conf │ ├── etalons │ │ └── patches │ │ │ ├── __init__.py │ │ │ └── software_upgrade.yaml │ ├── reports │ │ ├── __init__.py │ │ └── check_report.css │ ├── schemas │ │ ├── add_node.json │ │ ├── backup.json │ │ ├── cert_renew.json │ │ ├── check_paas.json │ │ ├── cluster.json │ │ ├── definitions │ │ │ ├── common │ │ │ │ ├── node_ref.json │ │ │ │ └── utils.json │ │ │ ├── gateway_node.json │ │ │ ├── globals.json │ │ │ ├── node.json │ │ │ ├── node_defaults.json │ │ │ ├── patch.json │ │ │ ├── plugin_defaults.json │ │ │ ├── plugins.json │ │ │ ├── plugins │ │ │ │ ├── calico.json │ │ │ │ ├── generic_plugin.json │ │ │ │ ├── installation.json │ │ │ │ ├── installation │ │ │ │ │ ├── ansible.json │ │ │ │ │ ├── config.json │ │ │ │ │ ├── expect.json │ │ │ │ │ ├── helm.json │ │ │ │ │ ├── python.json │ │ │ │ │ ├── shell.json │ │ │ │ │ └── template.json │ │ │ │ ├── kubernetes-dashboard.json │ │ │ │ ├── local-path-provisioner.json │ │ │ │ └── nginx-ingress-controller.json │ │ │ ├── procedures.json │ │ │ ├── rbac.json │ │ │ ├── rbac │ │ │ │ ├── account.json │ │ │ │ ├── account_defaults.json │ │ │ │ └── pss.json │ │ │ ├── registry.json │ │ │ ├── services.json │ │ │ ├── services │ │ │ │ ├── audit.json │ │ │ │ ├── coredns.json │ │ │ │ ├── cri.json │ │ │ │ ├── etc_hosts.json │ │ │ │ ├── kernel_security.json │ │ │ │ ├── kubeadm.json │ │ │ │ ├── kubeadm_kube-proxy.json │ │ │ │ ├── kubeadm_kubelet.json │ │ │ │ ├── kubeadm_patches.json │ │ │ │ ├── loadbalancer.json │ │ │ │ ├── modprobe.json │ │ │ │ ├── ntp.json │ │ │ │ ├── packages.json │ │ │ │ ├── packages │ │ │ │ │ └── associations.json │ │ │ │ ├── resolv.conf.json │ │ │ │ ├── sysctl.json │ │ │ │ └── thirdparties.json │ │ │ └── vrrp_ip.json │ │ ├── internal │ │ │ └── connections.json │ │ ├── manage_pss.json │ │ ├── migrate_kubemarine.json │ │ ├── reboot.json │ │ ├── reconfigure.json │ │ ├── remove_node.json │ │ ├── restore.json │ │ └── upgrade.json │ └── scripts │ │ ├── __init__.py │ │ ├── check_haproxy.sh │ │ ├── check_url_availability.py │ │ ├── etcdctl.sh │ │ ├── simple_port_client.py │ │ ├── simple_port_listener.py │ │ └── source │ │ └── ipip_check │ │ ├── go.mod │ │ ├── go.sum │ │ └── ipip_check.go ├── selinux.py ├── sysctl.py ├── system.py ├── templates │ ├── __init__.py │ ├── admission.yaml.j2 │ ├── haproxy.cfg.j2 │ ├── keepalived.conf.j2 │ ├── kubelet.service.j2 │ ├── patches │ │ ├── control-plane-pod.json.j2 │ │ └── kubelet.yaml.j2 │ └── plugins │ │ ├── __init__.py │ │ ├── calico-ippool.yaml.j2 │ │ ├── calico-kube-controllers-metrics.yaml │ │ ├── calico-metrics.yaml │ │ ├── calico-rr.sh.j2 │ │ ├── calico-rr.yaml.j2 │ │ ├── calico-typha-metrics.yaml │ │ ├── calicoctl.cfg.j2 │ │ ├── dashboard-ingress.yaml.j2 │ │ ├── dashboard-v2.5.yaml.j2 │ │ ├── dashboard-v2.7.yaml.j2 │ │ ├── iperf3.yaml.j2 │ │ ├── local-path-provisioner.yaml.j2 │ │ ├── nginx-ingress-controller-v1.2.yaml.j2 │ │ └── nginx-ingress-controller-v1.4.yaml.j2 ├── testsuite.py ├── thirdparties.py ├── version └── yum.py ├── pyproject.toml ├── requirements-pyinstaller.txt ├── scripts ├── ci │ ├── build_binary.py │ ├── custom-hooks │ │ └── hook-cryptography.py │ └── install_package.py └── thirdparties │ ├── .synccache │ └── .gitkeep │ ├── src │ ├── __init__.py │ ├── compatibility.py │ ├── run.py │ ├── shell.py │ ├── software │ │ ├── __init__.py │ │ ├── defaults.py │ │ ├── kubernetes_images.py │ │ ├── packages.py │ │ ├── plugins.py │ │ └── thirdparties.py │ └── tracker.py │ └── sync.py ├── setup.py └── test ├── __init__.py ├── resources └── fetch_os_versions_example.txt └── unit ├── __init__.py ├── core ├── __init__.py ├── test_cluster.py ├── test_env.py ├── test_executor.py ├── test_flow.py ├── test_group.py ├── test_jinja.py ├── test_registry.py ├── test_run_actions.py └── test_schema.py ├── plugins ├── __init__.py ├── test_builtin.py ├── test_calico.py ├── test_dashboard.py ├── test_helm.py ├── test_inventory.py ├── test_local_path_provisioner.py ├── test_nginx_ingress.py ├── test_template.py └── test_templates │ ├── test_template1.yaml │ ├── test_template2.yaml │ └── test_template3.yaml ├── test_add_node.py ├── test_admission.py ├── test_audit.py ├── test_backup.py ├── test_check_paas.py ├── test_config.py ├── test_coredns.py ├── test_cri_enrichment.py ├── test_defaults.py ├── test_demo.py ├── test_do.py ├── test_group.py ├── test_haproxy.py ├── test_install.py ├── test_inventory.py ├── test_k8s_cert.py ├── test_keepalived.py ├── test_kubernetes.py ├── test_kubernetes_components.py ├── test_manage_pss.py ├── test_migrate_kubemarine.py ├── test_modprobe.py ├── test_packages.py ├── test_reconfigure.py ├── test_remove_node.py ├── test_restore.py ├── test_sysctl.py ├── test_thirdparties.py ├── test_upgrade.py ├── test_workaround.py ├── tools ├── __init__.py └── thirdparties │ ├── __init__.py │ ├── stub.py │ └── test_sync.py └── utils.py /.dockerignore: -------------------------------------------------------------------------------- 1 | ci 2 | documentation 3 | dump 4 | ansible-inventory.ini 5 | cluster.yaml 6 | Dockerfile 7 | .git 8 | .DS_Store 9 | .gitignore 10 | .github 11 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | Please include a summary of the change and describe issue. Please also include relevant motivation and context. 3 | * 4 | 5 | Fixes # (issue) 6 | 7 | 8 | ### Solution 9 | Describe solution. List all changes that you made during implementation. 10 | * 11 | 12 | 13 | ### How to apply 14 | Provide steps how to apply on top previous Kubemarine version to execute on existing clusters 15 | * [Install task/s](documentation/Installation.md#installation-tasks-description) 16 | * Manual step 17 | * [Upgrade procedure](documentation/Maintenance.md#upgrade-procedure) 18 | 19 | 20 | ### Test Cases 21 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. 22 | 23 | **TestCase 1** 24 | 25 | Test Configuration: 26 | 27 | - Hardware: 28 | - OS: 29 | - Inventory: 30 | 31 | Steps: 32 | 33 | 1. 34 | 35 | Results: 36 | 37 | | Before | After | 38 | | ------ | ------ | 39 | | | | 40 | 41 | 42 | ### Checklist 43 | - [ ] I have commented my code, particularly in hard-to-understand areas 44 | - [ ] I have made corresponding changes to the documentation 45 | - [ ] There is no breaking changes, or migration patch is provided 46 | - [ ] Integration CI passed 47 | - [ ] Unit tests. If Yes list of new/changed tests with brief description 48 | - [ ] There is no merge conflicts 49 | 50 | 51 | #### Unit tests 52 | Indicate new or changed unit tests and what they do, if any. 53 | 54 | 55 | -------------------------------------------------------------------------------- /.github/workflows/docker.yaml: -------------------------------------------------------------------------------- 1 | name: Docker Image 2 | on: 3 | push: 4 | branches: 5 | - '**' 6 | tags: 7 | - '*' 8 | workflow_dispatch: 9 | inputs: 10 | publish_docker: 11 | description: "Publish image to ghcr.io/netcracker/kubemarine" 12 | type: boolean 13 | default: false 14 | required: false 15 | 16 | jobs: 17 | build-image: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Validate 21 | run: | 22 | if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.ref }}" == refs/tags* ]]; then 23 | echo -e "\033[91mManual workflow run on tags is not allowed!\033[0m" 24 | exit 1 25 | fi 26 | - name: Checkout Repo 27 | uses: actions/checkout@v3 28 | - name: Build Docker Image 29 | run: docker build -t kubemarine --no-cache . 30 | - name: Run Selftest 31 | # selftest of image internally runs selftest of package 32 | run: docker run kubemarine selftest 33 | - name: Publish to ghcr.io 34 | if: startsWith(github.ref, 'refs/tags') || github.ref_name == 'main' || inputs.publish_docker 35 | run: | 36 | GHCRIO_TAG=$(echo "${{ github.ref_name }}" | sed 's/\//_/g') 37 | GHCRIO_IMAGE=ghcr.io/netcracker/kubemarine:$GHCRIO_TAG 38 | 39 | docker tag kubemarine $GHCRIO_IMAGE 40 | 41 | echo -e "\033[0;32mPushing image ${GHCRIO_IMAGE}\033[0m" 42 | echo ${{ secrets.GITHUB_TOKEN }} | docker login https://ghcr.io -u $GITHUB_ACTOR --password-stdin 43 | docker push $GHCRIO_IMAGE 44 | -------------------------------------------------------------------------------- /.github/workflows/patch.yaml: -------------------------------------------------------------------------------- 1 | name: Manage Patches 2 | on: 3 | release: 4 | types: [released] 5 | jobs: 6 | delete_patches_on_release: 7 | runs-on: ubuntu-latest 8 | # Release can be done only in main branch or dedicated vN.N.N_branch support branches 9 | if: github.event.release.target_commitish == 'main' || endsWith(github.event.release.target_commitish, '_branch') 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | token: ${{ secrets.NCCLPLCI_PAT }} 14 | # By default, tag is checked out. It needs to check out branch to commit to. 15 | ref: ${{ github.event.release.target_commitish }} 16 | - run: | 17 | find kubemarine/patches/ -not -path "kubemarine/patches/__init__.py" -not -path "kubemarine/patches/" -delete 18 | cp kubemarine/resources/etalons/patches/* kubemarine/patches/ 19 | - uses: stefanzweifel/git-auto-commit-action@v4 20 | with: 21 | commit_message: Delete all patches after release 22 | -------------------------------------------------------------------------------- /.github/workflows/pypi.yaml: -------------------------------------------------------------------------------- 1 | name: Publish to PyPI 2 | on: 3 | release: 4 | types: [released] 5 | jobs: 6 | pypi: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Fetch Package 10 | uses: dsaltares/fetch-gh-release-asset@1.1.0 11 | with: 12 | version: ${{ github.event.release.id }} 13 | file: 'package.zip' 14 | token: ${{ secrets.GITHUB_TOKEN }} 15 | - name: Unpack Package 16 | run: unzip package.zip 17 | - name: Publish Package 18 | uses: pypa/gh-action-pypi-publish@v1.12.4 19 | with: 20 | password: ${{ secrets.PYPI_API_TOKEN }} 21 | -------------------------------------------------------------------------------- /.github/workflows/transfer_repo_image.yaml: -------------------------------------------------------------------------------- 1 | name: Build transfer image 2 | on: 3 | schedule: 4 | - cron: '0 0 * * 5' # Runs at 00:00 every Friday 5 | workflow_dispatch: 6 | inputs: 7 | publish: 8 | description: "Publish transfer image with binaries to ghcr.io/netcracker/kubemarine-transfer" 9 | type: boolean 10 | default: false 11 | required: false 12 | 13 | jobs: 14 | build-docker-transfer: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Archive bare repository 19 | run: | 20 | git clone --bare https://$GITHUB_ACTOR:${{ secrets.GITHUB_TOKEN }}@github.com/Netcracker/KubeMarine 21 | zip -r repository.zip KubeMarine.git 22 | - name: Build Docker Image for kubemarine-transfer 23 | run: docker build -t kubemarine-transfer -f ci/Dockerfile-transfer --no-cache . 24 | - name: Publish to ghcr.io 25 | if: github.ref_name == 'main' || inputs.publish 26 | run: | 27 | GHCRIO_TAG=$(echo "${{ github.ref_name }}" | sed 's/\//_/g') 28 | GHCRIO_IMAGE=ghcr.io/netcracker/kubemarine-transfer:$GHCRIO_TAG 29 | 30 | docker tag kubemarine-transfer $GHCRIO_IMAGE 31 | 32 | echo -e "\033[0;32mPushing image ${GHCRIO_IMAGE}\033[0m" 33 | echo ${{ secrets.GITHUB_TOKEN }} | docker login https://ghcr.io -u $GITHUB_ACTOR --password-stdin 34 | docker push $GHCRIO_IMAGE 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project-specific excludes 2 | kubeconfig 3 | /local_chart_folder 4 | !examples/* 5 | /dump 6 | ansible-inventory.ini 7 | admin.conf 8 | account-tokens.yaml 9 | cluster_finalized.yaml 10 | ca.csr 11 | ca.pem 12 | ca-key.pem 13 | kubernetes.csr 14 | kubernetes.pem 15 | kubernetes-key.pem 16 | /cluster*.yaml 17 | /additional.yaml 18 | /procedure.yaml 19 | venv/ 20 | build/ 21 | dist/ 22 | scripts/thirdparties/.synccache/* 23 | !scripts/thirdparties/.synccache/.gitkeep 24 | kubecheck 25 | kubecheck.zip 26 | report.* 27 | *.tar 28 | *.tar.gz 29 | *.log 30 | 31 | # System & software trash 32 | *~ 33 | .idea/ 34 | *.iml 35 | *.zip 36 | *.komodoproject 37 | .loadpath 38 | .project 39 | *.pyc 40 | .pydevproject 41 | *.pyo 42 | *.config_oc.yaml 43 | *.redcar* 44 | .*.swp 45 | .sass-cache 46 | .rvmrc 47 | .DS_Store 48 | .vagrant 49 | .tags* 50 | *.retry 51 | .vscode/ 52 | .cache 53 | .tox/ 54 | .coverage 55 | *.egg-info 56 | .eggs 57 | /Roadmap* 58 | Thumbs.db 59 | ehthumbs.db 60 | ehthumbs_vista.db 61 | *.stackdump 62 | [Dd]esktop.ini 63 | $RECYCLE.BIN/ 64 | *.cab 65 | *.msi 66 | *.msix 67 | *.msm 68 | *.msp 69 | *.lnk 70 | .AppleDouble 71 | .LSOverride 72 | Icon 73 | ._* 74 | .DocumentRevisions-V100 75 | .fseventsd 76 | .Spotlight-V100 77 | .TemporaryItems 78 | .Trashes 79 | .VolumeIcon.icns 80 | .com.apple.timemachine.donotpresent 81 | .AppleDB 82 | .AppleDesktop 83 | Network Trash Folder 84 | Temporary Items 85 | .apdisk 86 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This repository is governed by Netcracker code of conduct guidelines. 4 | 5 | We put collaboration, trust, respect and transparency as core values for our community. 6 | Our community welcomes participants from all over the world with different experience, 7 | opinion and ideas to share. 8 | 9 | We have adopted this code of conduct and require all contributors to agree with that to build a healthy, 10 | safe and productive community for all. 11 | 12 | The guideline is aimed to support a community where all people should feel safe to participate, 13 | introduce new ideas and inspire others, regardless of: 14 | * Age 15 | * Gender 16 | * Gender identity or expression 17 | * Family status 18 | * Marital status 19 | * Ability 20 | * Ethnicity 21 | * Race 22 | * Sex characteristics 23 | * Sexual identity and orientation 24 | * Education 25 | * Native language 26 | * Background 27 | * Caste 28 | * Religion 29 | * Geographic location 30 | * Socioeconomic status 31 | * Personal appearance 32 | * Any other dimension of diversity 33 | 34 | ## Our Standards 35 | 36 | We are welcoming the following behavior: 37 | * Be respectful for different ideas, opinions and points of view 38 | * Be constructive and professional 39 | * Use inclusive language 40 | * Be collaborative and show the empathy 41 | * Focus on the best results for the community 42 | 43 | The following behavior is unacceptable: 44 | * Violence, threats of violence, or inciting others to commit self-harm 45 | * Personal attacks, trolling, intentionally spreading misinformation, insulting/derogatory comments 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 48 | * Derogatory language 49 | * Encouraging unacceptable behavior 50 | * Other conduct which could reasonably be considered inappropriate in a professional community 51 | 52 | ## Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of the Code of Conduct 55 | and are expected to take appropriate actions in response to any instances of unacceptable behavior. 56 | 57 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 58 | commits, code, wiki edits, issues, and other contributions that are not aligned 59 | to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors 60 | that they deem inappropriate, threatening, offensive, or harmful. 61 | 62 | ## Reporting 63 | 64 | If you believe you’re experiencing unacceptable behavior that will not be tolerated as outlined above, 65 | please report to `opensourcegroup@netcracker.com`. All complaints will be reviewed and investigated and will result in a response 66 | that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality 67 | with regard to the reporter of an incident. 68 | 69 | Please also report if you observe a potentially dangerous situation, someone in distress, or violations of these guidelines, 70 | even if the situation is not happening to you. 71 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | We'd love to accept patches and contributions to this project. 4 | Please, follow these guidelines to make the contribution process easy and effective for everyone involved. 5 | 6 | ## Contributor License Agreement 7 | You must sign the [Contributor License Agreement](https://pages.netcracker.com/cla-main.html) in order to contribute. 8 | 9 | ## Code of Conduct 10 | Please make sure to read and follow the [Code of Conduct](CODE-OF-CONDUCT.md). 11 | 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | # Build ipip_check binary 4 | FROM golang:1.24 AS go-build 5 | 6 | WORKDIR /opt 7 | 8 | COPY ./kubemarine/resources/scripts/source/ipip_check ./ 9 | 10 | RUN go mod download && \ 11 | GOOS=linux CGO_ENABLED=1 go build -ldflags="-linkmode external -extldflags='-static'" -o ipip_check -buildvcs=false && \ 12 | gzip ipip_check 13 | 14 | FROM python:3.12-slim-bookworm AS python-build 15 | 16 | ARG BUILD_TYPE 17 | 18 | ENV PYTHONUNBUFFERED 1 19 | 20 | # Used in Ansible plugin. See Ansible documentation for more details 21 | ENV ANSIBLE_HOST_KEY_CHECKING False 22 | 23 | COPY . /opt/kubemarine/ 24 | COPY --from=go-build /opt/ipip_check.gz /opt/kubemarine/kubemarine/resources/scripts/ 25 | WORKDIR /opt/kubemarine/ 26 | 27 | RUN apt update && \ 28 | pip3 install --no-cache-dir setuptools wheel && \ 29 | pip3 install --no-cache-dir build && \ 30 | python3 -m build -n && \ 31 | # In any if branch delete source code, but preserve specific directories for different service aims 32 | if [ "$BUILD_TYPE" = "test" ]; then \ 33 | # Install from wheel with ansible to simulate real environment. 34 | pip3 install --no-cache-dir $(ls dist/*.whl)[ansible]; \ 35 | find -not -path "./test*" -not -path "./examples*" -not -path "./scripts*" -delete; \ 36 | elif [ "$BUILD_TYPE" = "package" ]; then \ 37 | find -not -path "./dist*" -delete; \ 38 | else \ 39 | pip3 install --no-cache-dir $(ls dist/*.whl)[ansible]; \ 40 | apt install -y wget; \ 41 | wget -O - https://get.helm.sh/helm-v3.17.3-linux-amd64.tar.gz | tar xvz -C /usr/local/bin linux-amd64/helm --strip-components 1; \ 42 | apt autoremove -y wget; \ 43 | rm -r *; \ 44 | fi && \ 45 | apt clean autoclean && \ 46 | rm -f /etc/apt/sources.list && \ 47 | rm -rf /var/lib/apt/lists/* 48 | 49 | ENTRYPOINT ["kubemarine"] 50 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | The maintainers are generally available in Slack at https://netcracker-tech.slack.com in #kubemarine channel. 2 | Additional direct contacts are: 3 | - Ilia github: @ilia1243 4 | - github: @theboringstuff 5 | - margarita github: @Imadzuma 6 | - Sergey github: @koryaga 7 | 8 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include kubemarine/plugins/yaml/* 2 | include kubemarine/version 3 | 4 | recursive-include kubemarine/patches * 5 | recursive-include kubemarine/resources * 6 | recursive-include kubemarine/templates * 7 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Reporting Process 2 | 3 | Please, report any security issue to `opensourcegroup@netcracker.com` where the issue will be triaged appropriately. 4 | 5 | If you know of a publicly disclosed security vulnerability please IMMEDIATELY email `opensourcegroup@netcracker.com` 6 | to inform Netcracker team about the vulnerability, so we may start the patch, release, and communication process. 7 | 8 | # Security Release Process 9 | 10 | If the vulnerability is found in the latest stable release, then it would be fixed in patch version for that release. 11 | E.g., issue is found in 2.5.0 release, then 2.5.1 version with a fix will be released. 12 | By default, older versions will not have security releases. 13 | 14 | If the issue doesn't affect any existing public releases, the fix for medium and high issues is performed 15 | in a main branch before releasing a new version. For low priority issues the fix can be planned for future releases. 16 | -------------------------------------------------------------------------------- /bin/kubemarine: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2021-2022 NetCracker Technology Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This env variable is used to force the stdout and stderr streams to be unbuffered in python. 17 | # By default we set this variable to true, because buffering sometimes causes very long output hanging => bad UX. 18 | # Users can override this variable and set it to false if unbuffered output causes any issues, but python output may 19 | # start hanging again. 20 | if [ -z "${PYTHONUNBUFFERED}" ]; then 21 | export PYTHONUNBUFFERED=TRUE 22 | fi 23 | 24 | # See pyproject.toml 25 | _kubemarine "$@" 26 | -------------------------------------------------------------------------------- /bin/kubemarine.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | REM This env variable is used to force the stdout and stderr streams to be unbuffered in python. 5 | REM By default we set this variable to true, because buffering sometimes causes very long output hanging => bad UX. 6 | REM Users can override this variable and set it to false if unbuffered output causes any issues, but python output may 7 | REM start hanging again. 8 | if not defined PYTHONUNBUFFERED ( 9 | set PYTHONUNBUFFERED=TRUE 10 | ) 11 | 12 | REM This env variable is used to ensure that possible redirect of stdout to files will use utf-8 encoding. 13 | if not defined PYTHONIOENCODING ( 14 | set PYTHONIOENCODING=utf-8 15 | ) 16 | 17 | REM See pyproject.toml 18 | _kubemarine %* 19 | -------------------------------------------------------------------------------- /ci/Dockerfile-transfer: -------------------------------------------------------------------------------- 1 | FROM alpine:3.16.1 2 | 3 | # Transfer 4 | COPY repository.zip ./transfer-repo/ 5 | -------------------------------------------------------------------------------- /ci/default_cluster.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: ~/.ssh/id_rsa 3 | username: runner 4 | 5 | nodes: 6 | - name: "node-all-in-one" 7 | address: "172.17.0.1" 8 | internal_address: "172.17.0.1" 9 | roles: ["control-plane", "worker"] 10 | 11 | cluster_name: "test-local-k8s.com" 12 | 13 | services: 14 | kubeadm: 15 | kubernetesVersion: '{{ env.KUBERNETES_VERSION }}' 16 | 17 | plugins: 18 | 19 | calico: 20 | install: true 21 | apiserver: 22 | enabled: true 23 | 24 | nginx-ingress-controller: 25 | install: true 26 | 27 | kubernetes-dashboard: 28 | install: true 29 | 30 | local-path-provisioner: 31 | install: true 32 | -------------------------------------------------------------------------------- /ci/extended_cluster.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: ~/.ssh/id_rsa 3 | username: runner 4 | 5 | nodes: 6 | - name: "node-all-in-one" 7 | address: "172.17.0.1" 8 | internal_address: "172.17.0.1" 9 | roles: ["balancer", "control-plane", "worker"] 10 | labels: 11 | test-label: label 12 | 13 | vrrp_ips: 14 | - ip: "172.17.1.1" 15 | 16 | cluster_name: "test-local-k8s.com" 17 | 18 | services: 19 | packages: 20 | install: 21 | - ethtool 22 | - ebtables 23 | - socat 24 | etc_hosts: 25 | 172.17.1.1: 26 | - dashboard.test-local-k8s.com 27 | 28 | plugins: 29 | kubernetes-dashboard: 30 | install: true 31 | nginx-ingress-controller: 32 | install: true 33 | controller: 34 | nodeSelector: 35 | test-label: label 36 | tolerations: 37 | - key: node-role.kubernetes.io/test-example 38 | operator: Exists 39 | effect: NoSchedule 40 | local-path-provisioner: 41 | install: true 42 | calico: 43 | install: true 44 | apiserver: 45 | enabled: true 46 | typha: 47 | enabled: true 48 | 49 | rbac: 50 | accounts: 51 | - name: superadmin 52 | role: cluster-admin 53 | - name: basic-user 54 | role: system:basic-user 55 | namespace: kube-system 56 | admission: pss 57 | pss: 58 | pod-security: enabled 59 | -------------------------------------------------------------------------------- /documentation/design/3-release-notes-management.md: -------------------------------------------------------------------------------- 1 | # 3. release notes management 2 | 3 | Date: 2024-05-23 4 | 5 | ## Status 6 | 7 | Proposal 8 | 9 | ## Context 10 | 11 | 1. There is Release Notes record published every release https://git.netcracker.com/PROD.Platform.HA/KubeMarine/-/releases. 12 | 2. There is a patch list released with each kubemarine version and used every migration procedure. https://github.com/Netcracker/KubeMarine/blob/main/documentation/Maintenance.md#patch-identifiers 13 | 3. This patch list is not published somewhere. No information in specific Release Notes about patches coming with this release which should be taken into account during migration procedure 14 | 4. During migration procedure, specially frue several releases, need to understand the patches to be applied and manage this process if necessary 15 | 16 | ## Decision 17 | 18 | Need to have a patch list within each Release Notes, including detailed information about patch 19 | 20 | ## Consequences 21 | 22 | What becomes easier or more difficult to do and any risks introduced by the change that will need to be mitigated. 23 | 24 | ## Considered Options 25 | 26 | 1. Update gitlab CI. Run in docker `migrate_kubemarine --list` and `migrate_kubemarine --describe` 27 | 2. Update githab CI. Run in `migrate_kubemarine --list` and `migrate_kubemarine --describe` 28 | 3. -------------------------------------------------------------------------------- /documentation/images/all-in-one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/documentation/images/all-in-one.png -------------------------------------------------------------------------------- /documentation/images/full-ha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/documentation/images/full-ha.png -------------------------------------------------------------------------------- /documentation/images/mini-ha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/documentation/images/mini-ha.png -------------------------------------------------------------------------------- /documentation/images/tls-termination-nginx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/documentation/images/tls-termination-nginx.png -------------------------------------------------------------------------------- /documentation/internal/Kubemarine-docker-building.md: -------------------------------------------------------------------------------- 1 | 1. Install latest [Docker CE](https://docs.docker.com/engine/install/) 2 | 2. Ensure Docker Engine is running 3 | 3. Clone this repository: `git clone https://github.com/Netcracker/KubeMarine.git` 4 | 4. Navigate inside project directory: `cd kubemarine` 5 | 5. Run building: `docker build . -t kubemarine --no-cache --progress=plain` 6 | 7 | Now you can proceed to run Kubemarine from container, for example: 8 | ``` 9 | docker run -it --mount type=bind,source=/root/cluster.yaml,target=/opt/kubemarine/cluster.yaml --mount type=bind,source=/root/rsa_key,target=/opt/kubemarine/rsa_key kubemarine install -c /opt/kubemarine/cluster.yaml 10 | ``` 11 | *Note:*: do not forget to pass inventory file and connection key inside container. 12 | For more execution details refer to ["Installation of Kubernetes using CLI" guide on Github](https://github.com/Netcracker/kubemarine/blob/main/documentation/Installation.md#installation-of-kubernetes-using-cli). 13 | 14 | *Hint:* it is possible to pass building arguments (use `--build-arg`) to build only package (argument `BUILD_TYPE=package`) or build image with testing tools included (argument `BUILD_TYPE=test`). 15 | -------------------------------------------------------------------------------- /documentation/internal/NetworkPerfomance.md: -------------------------------------------------------------------------------- 1 | # Network Perfomance Benchmark 2 | 3 | Source [https://github.com/Pharb/kubernetes-iperf3](https://github.com/Pharb/kubernetes-iperf3). 4 | 5 | To check the cluster network performance, it is necessary to do the following: 6 | 7 | 1. Add the following configuration to the **plugins** section: 8 | ```yaml 9 | plugins: 10 | iperf3: 11 | install: true 12 | installation: 13 | procedures: 14 | - template: templates/plugins/iperf3.yaml.j2 15 | expect: 16 | pods: 17 | - iperf3-server 18 | - iperf3-clients 19 | ``` 20 | 21 | For this plugin, it is possible to configure nodeSelector, so that all iperf3 pods will be ran only on particular nodes: 22 | ```yaml 23 | plugins: 24 | iperf3: 25 | nodeSelector: 26 | role: compute 27 | ``` 28 | Also, it is possible to configure tolerations, so that iperf3 pods will be able to run on master, for example: 29 | ```yaml 30 | plugins: 31 | iperf3: 32 | tolerations: 33 | - key: node-role.kubernetes.io/control-plane 34 | effect: NoSchedule 35 | ``` 36 | 37 | 2. Run the [installation](documentation/public/Installation.md) procedure and wait until it is completed. 38 | 3. Go to any control-plane node, and run the following script: 39 | ```bash 40 | #!/usr/bin/env bash 41 | set -eu 42 | 43 | CLIENTS=$(kubectl get pods -n iperf3 -l app=iperf3-client -o name | cut -d'/' -f2) 44 | 45 | for POD in ${CLIENTS}; do 46 | until $(kubectl get pod -n iperf3 ${POD} -o jsonpath='{.status.containerStatuses[0].ready}'); do 47 | echo "Waiting for ${POD} to start..." 48 | sleep 5 49 | done 50 | HOST=$(kubectl get pod -n iperf3 ${POD} -o jsonpath='{.status.hostIP}') 51 | kubectl exec -n iperf3 -it ${POD} -- iperf3 -c iperf3-server -T "Client on ${HOST}" $@ 52 | echo 53 | done 54 | ``` 55 | 4. Once the benchmark is finished, remove the plugin using the following command: 56 | ```bash 57 | # kubectl delete --cascade -f /etc/kubernetes/iperf3.yaml 58 | ``` 59 | -------------------------------------------------------------------------------- /documentation/internal/Release.md: -------------------------------------------------------------------------------- 1 | # Releasing KubeMarine 2 | 3 | If you want to make a new KubeMarine release, you need to do following: 4 | 1. On the `main` branch, update KubeMarine version and create tag (replace `X.X.X` with actual version): 5 | ``` 6 | python3 -m pip install bumpver 7 | python3 -m bumpver update --set-version=X.X.X 8 | ``` 9 | 2. Wait for [GitHub Actions](https://github.com/Netcracker/KubeMarine/actions) completion and verify newly create pre-release on [GitHub Release page](https://github.com/Netcracker/KubeMarine/releases). Following artifacts are essential for each release: 10 | * KubeMarine binaries for different OS. They could be found in release assets. 11 | * KubeMarine python distribution package. It could be found in release assets. 12 | * [KubeMarine image](https://github.com/Netcracker/KubeMarine/pkgs/container/kubemarine). 13 | * [Kubemarine documentation](https://github.com/Netcracker/KubeMarine/tree/main/documentation). 14 | 3. Once you have verified that KubeMarine artifacts are OK, change your release from `pre-release` to `latest release` on [GitHub Release page](https://github.com/Netcracker/KubeMarine/releases). This will publish KubeMarine distribution package to PyPI. 15 | -------------------------------------------------------------------------------- /examples/cluster.yaml/allinone-cluster-ol7.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: /home/user/id_rsa 3 | password: '{{ env.PASS }}' #Either keyfile or password can be used. 4 | username: cloud-user 5 | 6 | vrrp_ips: 7 | - ip: "192.168.1.200" 8 | nodes: 9 | - name: "k8s3" 10 | address: "10.101.0.2" 11 | internal_address: "192.168.1.9" 12 | roles: ["control-plane", "worker", "balancer"] 13 | cluster_name: "k8s.oracle.com" 14 | 15 | services: 16 | resolv.conf: 17 | nameservers: 18 | - 1.1.1.1 19 | - 1.0.0.1 20 | 21 | ntp: 22 | # For RHEL OS use chrony: 23 | chrony: 24 | servers: 25 | - 0.de.pool.ntp.org iburst 26 | - 1.de.pool.ntp.org iburst 27 | makestep: 5 10 28 | rtcsync: True 29 | 30 | packages: 31 | package_manager: 32 | replace-repositories: false 33 | repositories: 34 | # Own OL7 repositories need to be described in cluster.yaml, if they are disabled in OS. 35 | ol7_addons: 36 | name: "Oracle Linux Addons" 37 | enabled: 1 38 | gpgcheck: 0 39 | baseurl: "https://yum.oracle.com/repo/OracleLinux/OL7/addons/x86_64/" 40 | ol7_latest: 41 | name: "Oracle Linux Latest" 42 | enabled: 1 43 | gpgcheck: 0 44 | baseurl: "https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64" 45 | docker-ce: 46 | name: "CentOS 7 Docker-CE" 47 | enabled: 1 48 | gpgcheck: 0 49 | baseurl: "https://download.docker.com/linux/centos/7/x86_64/stable/" 50 | centos-sclo-haproxy18: 51 | name: "CentOS SCLO rh-haproxy18" 52 | enabled: 1 53 | gpgcheck: 0 54 | baseurl: "http://mirror.centos.org/centos/7/sclo/x86_64/rh/" 55 | 56 | install: 57 | - conntrack-tools 58 | - kmod 59 | - ethtool 60 | - ebtables 61 | - socat 62 | - curl 63 | - openssl 64 | - unzip 65 | - policycoreutils-python 66 | associations: 67 | containerd: 68 | package_name: 69 | - 'containerd.io-1.4.6*' 70 | 71 | rbac: 72 | accounts: 73 | - name: superadmin 74 | role: cluster-admin 75 | 76 | plugins: 77 | kubernetes-dashboard: 78 | install: true 79 | -------------------------------------------------------------------------------- /examples/cluster.yaml/allinone-cluster.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: "/home/username/.ssh/id_rsa" 3 | password: '{{ env.PASS }}' #Either keyfile or password can be used. 4 | username: "centos" 5 | 6 | nodes: 7 | - name: "k8s-control-plane" 8 | address: "10.101.0.1" 9 | internal_address: "192.168.0.1" 10 | roles: ["control-plane", "worker"] 11 | 12 | cluster_name: "k8s.example.com" 13 | -------------------------------------------------------------------------------- /examples/cluster.yaml/miniha-cluster.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: "/home/username/.ssh/id_rsa" 3 | password: '{{ env.PASS }}' #Either keyfile or password can be used. 4 | username: "centos" 5 | 6 | vrrp_ips: 7 | - 192.168.0.250 8 | 9 | nodes: 10 | - name: "k8s-control-plane-1" 11 | address: "10.101.0.1" 12 | internal_address: "192.168.0.1" 13 | roles: ["balancer", "control-plane", "worker"] 14 | - name: "k8s-control-plane-2" 15 | address: "10.101.0.2" 16 | internal_address: "192.168.0.2" 17 | roles: ["balancer", "control-plane", "worker"] 18 | - name: "k8s-control-plane-3" 19 | address: "10.101.0.3" 20 | internal_address: "192.168.0.3" 21 | roles: ["balancer", "control-plane", "worker"] 22 | 23 | cluster_name: "k8s.example.com" 24 | -------------------------------------------------------------------------------- /examples/cluster.yaml/minimal-cluster.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: "/home/username/.ssh/id_rsa" 3 | password: '{{ env.PASS }}' #Either keyfile or password can be used. 4 | username: "centos" 5 | 6 | nodes: 7 | - name: "k8s-lb" 8 | address: "10.101.0.1" 9 | internal_address: "192.168.0.1" 10 | roles: ["balancer"] 11 | - name: "k8s-control-plane-1" 12 | address: "10.101.0.2" 13 | internal_address: "192.168.0.2" 14 | roles: ["control-plane"] 15 | - name: "k8s-control-plane-2" 16 | address: "10.101.0.3" 17 | internal_address: "192.168.0.3" 18 | roles: ["control-plane"] 19 | - name: "k8s-control-plane-3" 20 | address: "10.101.0.4" 21 | internal_address: "192.168.0.4" 22 | roles: ["control-plane"] 23 | - name: "k8s-worker-1" 24 | address: "10.101.0.5" 25 | internal_address: "192.168.0.5" 26 | roles: ["worker"] 27 | - name: "k8s-worker-2" 28 | address: "10.101.0.6" 29 | internal_address: "192.168.0.6" 30 | roles: ["worker"] 31 | - name: "k8s-worker-3" 32 | address: "10.101.0.7" 33 | internal_address: "192.168.0.7" 34 | roles: ["worker"] 35 | 36 | cluster_name: "k8s.example.com" 37 | -------------------------------------------------------------------------------- /examples/cluster.yaml/typical-cluster.yaml: -------------------------------------------------------------------------------- 1 | node_defaults: 2 | keyfile: "/home/username/.ssh/id_rsa" 3 | password: '{{ env.PASS }}' #Either keyfile or password can be used. 4 | username: "centos" 5 | 6 | vrrp_ips: 7 | - 192.168.0.250 8 | 9 | nodes: 10 | - name: "k8s-lb-1" 11 | address: "10.101.0.1" 12 | internal_address: "192.168.0.1" 13 | roles: ["balancer"] 14 | - name: "k8s-lb-2" 15 | address: "10.101.0.2" 16 | internal_address: "192.168.0.2" 17 | roles: ["balancer"] 18 | - name: "k8s-control-plane-1" 19 | address: "10.101.0.3" 20 | internal_address: "192.168.0.3" 21 | roles: ["control-plane"] 22 | - name: "k8s-control-plane-2" 23 | address: "10.101.0.4" 24 | internal_address: "192.168.0.4" 25 | roles: ["control-plane"] 26 | - name: "k8s-control-plane-3" 27 | address: "10.101.0.5" 28 | internal_address: "192.168.0.5" 29 | roles: ["control-plane"] 30 | - name: "k8s-worker-1" 31 | address: "10.101.0.6" 32 | internal_address: "192.168.0.6" 33 | roles: ["worker"] 34 | - name: "k8s-worker-2" 35 | address: "10.101.0.7" 36 | internal_address: "192.168.0.7" 37 | roles: ["worker"] 38 | - name: "k8s-worker-3" 39 | address: "10.101.0.8" 40 | internal_address: "192.168.0.8" 41 | roles: ["worker"] 42 | 43 | cluster_name: "k8s.example.com" 44 | 45 | services: 46 | resolv.conf: 47 | search: default 48 | nameservers: 49 | - 1.1.1.1 50 | - 1.0.0.1 51 | - 2606:4700:4700::1111 52 | - 2606:4700:4700::1001 53 | 54 | ntp: 55 | # For RHEL OS use chrony. Uncomment and customize the following section: 56 | # chrony: 57 | # servers: 58 | # - 0.de.pool.ntp.org iburst 59 | # - 1.de.pool.ntp.org iburst 60 | # makestep: 5 10 61 | # rtcsync: True 62 | 63 | # For Debian OS use timesyncd: 64 | timesyncd: 65 | Time: 66 | NTP: 67 | - 0.de.pool.ntp.org 68 | - 1.de.pool.ntp.org 69 | FallbackNTP: 70 | - 2.de.pool.ntp.org 71 | - 3.de.pool.ntp.org 72 | RootDistanceMaxSec: 10 73 | PollIntervalMinSec: 64 74 | PollIntervalMaxSec: 1024 75 | 76 | packages: 77 | package_manager: 78 | replace-repositories: true 79 | # For RHEL OS use yum-like format: 80 | repositories: 81 | centos-sclo-haproxy18: 82 | name: "CentOS SCLO rh-haproxy18" 83 | enabled: 1 84 | gpgcheck: 0 85 | baseurl: "http://mirror.centos.org/centos/7/sclo/x86_64/rh/rh-haproxy18/" 86 | # For Debian OS use apt-like format: 87 | # repositories: 88 | # - "deb [arch=amd64 trusted=yes] http://example.com/deb/ubuntu/ focal main restricted" 89 | install: 90 | include: 91 | - ethtool 92 | - ebtables 93 | - socat 94 | - curl 95 | - openssl 96 | - unzip 97 | - policycoreutils-python 98 | 99 | rbac: 100 | accounts: 101 | - name: superadmin 102 | role: cluster-admin 103 | 104 | plugins: 105 | kubernetes-dashboard: 106 | install: true 107 | -------------------------------------------------------------------------------- /examples/procedure.yaml/full-backup.yaml: -------------------------------------------------------------------------------- 1 | backup_location: /home/centos 2 | 3 | backup_plan: 4 | etcd: 5 | source_node: control-plane-1 6 | nodes: 7 | /etc/resolv.conf: True 8 | /root: True 9 | /etc/hosts: False 10 | kubernetes: 11 | namespaced_resources: 12 | namespaces: all 13 | resources: all 14 | nonnamespaced_resources: all 15 | -------------------------------------------------------------------------------- /examples/procedure.yaml/full-reboot.yaml: -------------------------------------------------------------------------------- 1 | graceful_reboot: True 2 | 3 | nodes: 4 | - name: control-plane-1 5 | - name: control-plane-2 6 | - name: control-plane-3 7 | -------------------------------------------------------------------------------- /examples/procedure.yaml/full-restore.yaml: -------------------------------------------------------------------------------- 1 | backup_location: /home/centos/backup.tar.gz 2 | 3 | restore_plan: 4 | etcd: 5 | image: registry.k8s.io/etcd:3.3.15-0 6 | certificates: 7 | cert: /etc/kubernetes/pki/etcd/server.crt 8 | key: /etc/kubernetes/pki/etcd/server.key 9 | cacert: /etc/kubernetes/pki/etcd/ca.crt 10 | peer_cert: /etc/kubernetes/pki/etcd/peer.crt 11 | peer_key: /etc/kubernetes/pki/etcd/peer.key 12 | peer_cacert: /etc/kubernetes/pki/etcd/ca.crt 13 | thirdparties: 14 | /usr/bin/kubeadm: 15 | source: https://dl.k8s.io/v1.18.8/bin/linux/amd64/kubeadm 16 | /usr/bin/kubelet: 17 | source: https://dl.k8s.io/v1.18.8/bin/linux/amd64/kubelet 18 | /usr/bin/kubectl: 19 | source: https://dl.k8s.io/v1.18.8/bin/linux/amd64/kubectl 20 | /opt/cni/cni-plugins-linux.tgz: 21 | source: https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-amd64-v0.8.6.tgz 22 | /usr/bin/calicoctl: 23 | source: https://github.com/projectcalico/calicoctl/releases/download/v3.14.1/calicoctl-linux-amd64 24 | -------------------------------------------------------------------------------- /examples/procedure.yaml/minimal-backup.yaml: -------------------------------------------------------------------------------- 1 | backup_plan: 2 | nodes: 3 | /etc/resolv.conf: True 4 | /root: True 5 | /etc/hosts: False 6 | -------------------------------------------------------------------------------- /examples/procedure.yaml/minimal-restore.yaml: -------------------------------------------------------------------------------- 1 | backup_location: /home/centos/backup.tar.gz 2 | -------------------------------------------------------------------------------- /kubemarine.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/kubemarine.ico -------------------------------------------------------------------------------- /kubemarine.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | block_cipher = None 4 | options = [ ('u', None, 'OPTION')] 5 | 6 | # MacOS option. By default, current running architecture is targeted. 7 | # See scripts/ci/build_binary.py 8 | target_arch = None 9 | 10 | a = Analysis(['./kubemarine/__main__.py'], 11 | hiddenimports=[ 12 | # Dynamically imported `python` procedures for plugins in defaults.yaml 13 | 'kubemarine.plugins.builtin', 14 | 'kubemarine.plugins.calico', 15 | 'kubemarine.plugins.nginx_ingress', 16 | 'kubemarine.plugins.kubernetes_dashboard', 17 | ], 18 | pathex=[], 19 | binaries=[], 20 | datas=[ 21 | ('./kubemarine/patches', './kubemarine/patches'), 22 | ('./kubemarine/plugins', './kubemarine/plugins'), 23 | ('./kubemarine/version', './kubemarine/'), 24 | ('./kubemarine/resources', './kubemarine/resources'), 25 | ('./kubemarine/templates', './kubemarine/templates') 26 | ], 27 | hookspath=['scripts/ci/custom-hooks'], 28 | runtime_hooks=[], 29 | excludes=[], 30 | win_no_prefer_redirects=False, 31 | win_private_assemblies=False, 32 | cipher=block_cipher, 33 | noarchive=False) 34 | 35 | pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) 36 | 37 | exe = EXE(pyz, 38 | a.scripts, 39 | a.binaries, 40 | a.zipfiles, 41 | a.datas, 42 | options, 43 | exclude_binaries=False, 44 | name='kubemarine', 45 | icon='kubemarine.ico', 46 | debug=False, 47 | bootloader_ignore_signals=False, 48 | strip=False, 49 | upx=True, 50 | console=True, 51 | target_arch=target_arch, 52 | ) 53 | -------------------------------------------------------------------------------- /kubemarine/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /kubemarine/core/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/core/action.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from abc import ABC, abstractmethod 16 | 17 | from kubemarine.core.resources import DynamicResources 18 | 19 | 20 | class Action(ABC): 21 | """Base class for doing some work based on provided DynamicResources""" 22 | 23 | def __init__(self, identifier: str, *, recreate_inventory: bool = False) -> None: 24 | """ 25 | Constructor of Action to be invoked from derived classes. 26 | 27 | :param identifier: action identifier, which will be preserved on nodes 28 | if the action is successfully performed. 29 | :param recreate_inventory: Specifies if inventory should be recreated after the action succeeds. 30 | """ 31 | 32 | self.identifier = identifier 33 | self.recreate_inventory = recreate_inventory 34 | 35 | @abstractmethod 36 | def run(self, _res: DynamicResources) -> None: 37 | """ 38 | Do some work based on provided DynamicResources. If any action fails, further actions are not run. 39 | 40 | Avoid direct exiting in case of exceptions (for example using utils.do_fail), 41 | unless it is the only action being executed. 42 | Otherwise, correct exception handling will not be performed. 43 | """ 44 | pass 45 | 46 | def prepare_context(self, context: dict) -> None: 47 | """ 48 | Enrich context if necessary before the action is run. 49 | The changes are remained after action is executed, and will be visible to further actions. 50 | 51 | :param context: mutable context instance. 52 | """ 53 | pass 54 | -------------------------------------------------------------------------------- /kubemarine/core/annotations.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | from typing import Callable, TypeVar 15 | 16 | from typing_extensions import ParamSpec 17 | 18 | from kubemarine.core.group import NodeGroup 19 | 20 | 21 | _P = ParamSpec('_P') 22 | _T = TypeVar('_T') 23 | 24 | 25 | def restrict_multi_os_group(fn: Callable[_P, _T]) -> Callable[_P, _T]: 26 | """ 27 | Method is an annotation that does not allow origin method to use different OS families in the same group. 28 | :param fn: Origin function to apply annotation validation to 29 | :return: Validation wrapper function 30 | """ 31 | def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T: 32 | group = next((g for g in args if isinstance(g, NodeGroup)), None) 33 | if group is None: 34 | raise Exception("Failed to find argument of NodeGroup type") 35 | if group.is_multi_os(): 36 | raise Exception(f'Method "{str(fn)}" do not supports multi-os group') 37 | return fn(*args, **kwargs) 38 | return wrapper 39 | 40 | 41 | def restrict_empty_group(fn: Callable[_P, _T]) -> Callable[_P, _T]: 42 | """ 43 | Method is an annotation that prohibits passing empty groups to the function. 44 | :param fn: Origin function to apply annotation validation to 45 | :return: Validation wrapper function 46 | """ 47 | def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T: 48 | group = next((g for g in args if isinstance(g, NodeGroup)), None) 49 | if group is None: 50 | raise Exception("Failed to find argument of NodeGroup type") 51 | if group.is_empty(): 52 | raise Exception(f'Method "{str(fn)}" prohibits passing empty groups to it') 53 | return fn(*args, **kwargs) 54 | return wrapper 55 | -------------------------------------------------------------------------------- /kubemarine/core/environment.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | from abc import ABC, abstractmethod 17 | 18 | from kubemarine.core import log 19 | from kubemarine.core.connections import ConnectionPool 20 | 21 | 22 | class Environment(ABC): 23 | @property 24 | @abstractmethod 25 | def connection_pool(self) -> ConnectionPool: 26 | pass 27 | 28 | @property 29 | @abstractmethod 30 | def log(self) -> log.EnhancedLogger: 31 | pass 32 | 33 | @staticmethod 34 | def is_deploying_from_windows() -> bool: 35 | return os.name == 'nt' 36 | -------------------------------------------------------------------------------- /kubemarine/core/os.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | from typing import Iterator, Mapping, List 17 | 18 | 19 | class Environ(Mapping[str, str]): 20 | """ 21 | Read-only view of os.environ. 22 | """ 23 | 24 | def __getitem__(self, name: str) -> str: 25 | # check presence of the variable and throw KeyError if necessary 26 | return os.environ[name] 27 | 28 | def __len__(self) -> int: 29 | return len(os.environ) 30 | 31 | def __iter__(self) -> Iterator[str]: 32 | return iter(os.environ) 33 | 34 | __slots__: List[str] = [] 35 | -------------------------------------------------------------------------------- /kubemarine/core/patch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import enum 15 | from abc import ABC, abstractmethod 16 | from functools import total_ordering 17 | 18 | from kubemarine.core.action import Action 19 | 20 | 21 | @total_ordering 22 | class _Priority(enum.Enum): 23 | INVENTORY_ONLY = 0 24 | """ 25 | The patch may change the inventory. 26 | The patch can run only LIGHT enrichment, and connect to nodes for read-only aims. 27 | """ 28 | 29 | SOFTWARE_UPGRADE = 1 30 | "This is a service patch that should be instantiated only automatically by migrate_kubemarine.py" 31 | 32 | REGULAR = 2 33 | """ 34 | The patch can access and make some operations on the cluster. 35 | Changes in the inventory are possible, but they should not affect the software upgrade procedure. 36 | """ 37 | 38 | def __lt__(self, other: '_Priority') -> bool: 39 | return self.value < other.value 40 | 41 | 42 | class Patch(ABC): 43 | def __init__(self, identifier: str): 44 | self.identifier = identifier 45 | 46 | @abstractmethod 47 | def priority(self) -> _Priority: 48 | pass 49 | 50 | @property 51 | @abstractmethod 52 | def action(self) -> Action: 53 | pass 54 | 55 | @property 56 | @abstractmethod 57 | def description(self) -> str: 58 | pass 59 | 60 | 61 | class InventoryOnlyPatch(Patch, ABC): 62 | """ 63 | The patch may change the inventory. 64 | Calling DynamicResources.cluster(EnrichmentStage.LIGHT) is allowed to connect to nodes for read-only aims. 65 | 66 | Patches if this type are executed first. 67 | """ 68 | 69 | def priority(self) -> _Priority: 70 | return _Priority.INVENTORY_ONLY 71 | 72 | 73 | class _SoftwareUpgradePatch(Patch, ABC): 74 | """This is a service patch that should be extended only by predefined set of classes inside migrate_kubemarine.py""" 75 | 76 | def priority(self) -> _Priority: 77 | return _Priority.SOFTWARE_UPGRADE 78 | 79 | 80 | class RegularPatch(Patch, ABC): 81 | """ 82 | The patch can access and make some operations on the cluster. 83 | 84 | Changes in the inventory are possible, 85 | but the cluster should be `DynamicResources.reset_cluster()` for the changes to take effect. 86 | The changes in the inventory should also not affect the software upgrade procedure. 87 | 88 | Patches if this type are executed last. 89 | """ 90 | 91 | def priority(self) -> _Priority: 92 | return _Priority.REGULAR 93 | -------------------------------------------------------------------------------- /kubemarine/core/static.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from kubemarine.core import utils 16 | 17 | 18 | def reload() -> None: 19 | GLOBALS.clear() 20 | GLOBALS.update(_load_globals()) 21 | 22 | DEFAULTS.clear() 23 | DEFAULTS.update(_load_defaults()) 24 | 25 | KUBERNETES_VERSIONS.clear() 26 | KUBERNETES_VERSIONS.update(load_kubernetes_versions()) 27 | 28 | 29 | def load_compatibility_map(filename: str) -> dict: 30 | return utils.load_yaml(utils.get_internal_resource_path( 31 | f"resources/configurations/compatibility/internal/{filename}")) 32 | 33 | 34 | def load_kubernetes_versions() -> dict: 35 | kubernetes_versions = utils.load_yaml( 36 | utils.get_internal_resource_path('resources/configurations/compatibility/kubernetes_versions.yaml')) 37 | 38 | return kubernetes_versions 39 | 40 | 41 | def _load_globals() -> dict: 42 | globals_ = utils.load_yaml( 43 | utils.get_internal_resource_path('resources/configurations/globals.yaml')) 44 | 45 | for config_filename in ('kubernetes_images.yaml', 'packages.yaml', 'plugins.yaml', 'thirdparties.yaml'): 46 | internal_compatibility = load_compatibility_map(config_filename) 47 | 48 | globals_compatibility = globals_['compatibility_map']['software'] 49 | duplicates = set(internal_compatibility) & set(globals_compatibility) 50 | if duplicates: 51 | raise Exception(f"Duplicated software {', '.join(repr(s) for s in duplicates)}") 52 | 53 | globals_compatibility.update(internal_compatibility) 54 | 55 | return globals_ 56 | 57 | 58 | def _load_defaults() -> dict: 59 | return utils.load_yaml( 60 | utils.get_internal_resource_path('resources/configurations/defaults.yaml')) 61 | 62 | 63 | GLOBALS: dict = {} 64 | DEFAULTS: dict = {} 65 | KUBERNETES_VERSIONS: dict = {} 66 | 67 | reload() 68 | -------------------------------------------------------------------------------- /kubemarine/core/summary.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import enum 16 | from functools import total_ordering 17 | from typing import Dict, Callable 18 | 19 | from kubemarine.core import log 20 | from kubemarine.core.cluster import KubernetesCluster 21 | 22 | 23 | @total_ordering 24 | class SummaryItem(enum.Enum): 25 | KUBECONFIG = (0, "Kubeconfig") 26 | DASHBOARD_URL = (1, "Dashboard URL") 27 | CONTROL_PLANES = (2, "Running Control Planes") 28 | WORKERS = (3, "Running Workers") 29 | ACCOUNT_TOKENS = (4, "Account Tokens File") 30 | EXECUTION_TIME = (5, "Elapsed") 31 | 32 | def __init__(self, order: int, text: str) -> None: 33 | self.order = order 34 | self.text = text 35 | 36 | def __lt__(self, other: 'SummaryItem') -> bool: 37 | return self.order < other.order 38 | 39 | 40 | def schedule_report(context: dict, property_: SummaryItem, value: str) -> None: 41 | context.setdefault('summary_report', {})[property_] = value 42 | 43 | 44 | def schedule_delayed_report(cluster: KubernetesCluster, call: Callable[[KubernetesCluster], None]) -> None: 45 | cluster.context.setdefault('delayed_summary_report', []).append(call) 46 | cluster.schedule_cumulative_point(exec_delayed) 47 | 48 | 49 | def print_summary(context: dict, logger: log.EnhancedLogger) -> None: 50 | summary_items: Dict[SummaryItem, str] = context.get('summary_report', {}) 51 | max_length = max(len(si.text) for si in summary_items.keys()) 52 | logger.info('') 53 | for si, value in sorted(summary_items.items()): 54 | key = si.text + ': ' + (' ' * (max_length - len(si.text))) 55 | logger.info(key + value) 56 | 57 | 58 | def exec_delayed(cluster: KubernetesCluster) -> None: 59 | for call in cluster.context.get('delayed_summary_report', []): 60 | call(cluster) 61 | -------------------------------------------------------------------------------- /kubemarine/core/yaml_merger.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | from typing import Tuple, Optional 15 | 16 | from deepmerge import Merger # type: ignore[import-untyped] 17 | 18 | 19 | def is_list_extends(nxt: list, path: list) -> bool: 20 | return get_strategy_position(nxt, path)[0] == 'merge' 21 | 22 | 23 | def get_strategy_position(nxt: list, path: list) -> Tuple[Optional[str], int]: 24 | strategy = None 25 | strategy_definition_position = 0 26 | for i, v in enumerate(nxt): 27 | if isinstance(v, dict) and '<<' in v: 28 | if strategy is not None: 29 | raise Exception(f"Found more than one merge strategy definitions at path {path}.") 30 | strategy = v.get('<<') 31 | strategy_definition_position = i 32 | if v.keys() != {'<<'} or strategy not in ('replace', 'merge'): 33 | raise Exception(f"Unexpected merge strategy definition {v} at path {path}.") 34 | 35 | return strategy, strategy_definition_position 36 | 37 | 38 | def list_merger(_: Merger, path: list, base: list, nxt: list) -> list: 39 | strategy, strategy_definition_position = get_strategy_position(nxt, path) 40 | 41 | if strategy is None: 42 | return nxt 43 | 44 | elements_after = nxt[(strategy_definition_position + 1):] 45 | elements_before = nxt[:strategy_definition_position] 46 | # do not modify source list 47 | nxt = [] 48 | nxt.extend(elements_before) 49 | if strategy == 'merge': 50 | nxt.extend(base) 51 | nxt.extend(elements_after) 52 | 53 | return nxt 54 | 55 | 56 | default_merger: Merger = Merger( 57 | [ 58 | (list, [list_merger]), 59 | (dict, ["merge"]) 60 | ], 61 | ["override"], 62 | ["override"] 63 | ) 64 | 65 | override_merger: Merger = Merger( 66 | [ 67 | (list, ["override"]), 68 | (dict, ["merge"]) 69 | ], 70 | ["override"], 71 | ["override"] 72 | ) 73 | -------------------------------------------------------------------------------- /kubemarine/cri/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | from kubemarine.core.cluster import KubernetesCluster, EnrichmentStage, enrichment 15 | from kubemarine.core.group import RunnersGroupResult, NodeGroup 16 | from kubemarine.cri import containerd 17 | 18 | 19 | @enrichment(EnrichmentStage.FULL) 20 | def enrich_inventory(cluster: KubernetesCluster) -> None: 21 | containerd.enrich_inventory(cluster) 22 | 23 | 24 | @enrichment(EnrichmentStage.PROCEDURE, procedures=['upgrade']) 25 | def enrich_upgrade_inventory(cluster: KubernetesCluster) -> None: 26 | containerd.enrich_upgrade_inventory(cluster) 27 | 28 | 29 | @enrichment(EnrichmentStage.PROCEDURE, procedures=['upgrade']) 30 | def verify_upgrade_inventory(cluster: KubernetesCluster) -> None: 31 | containerd.verify_upgrade_inventory(cluster) 32 | 33 | 34 | def install(group: NodeGroup) -> RunnersGroupResult: 35 | return containerd.install(group) 36 | 37 | 38 | def configure(group: NodeGroup) -> RunnersGroupResult: 39 | return containerd.configure(group) 40 | 41 | 42 | def prune(group: NodeGroup) -> RunnersGroupResult: 43 | return containerd.prune(group) 44 | -------------------------------------------------------------------------------- /kubemarine/k8s_certs.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | from typing import List 15 | 16 | from kubemarine import kubernetes 17 | from kubemarine.core.cluster import KubernetesCluster, EnrichmentStage, enrichment 18 | from kubemarine.core.group import NodeGroup 19 | 20 | 21 | def k8s_certs_overview(control_planes: NodeGroup) -> None: 22 | for control_plane in control_planes.get_ordered_members_list(): 23 | control_planes.cluster.log.debug(f"Checking certs expiration for control_plane {control_plane.get_node_name()}") 24 | control_plane.sudo("kubeadm certs check-expiration", hide=False, pty=True) 25 | 26 | 27 | @enrichment(EnrichmentStage.PROCEDURE, procedures=['cert_renew']) 28 | def renew_verify(cluster: KubernetesCluster) -> None: 29 | if "kubernetes" not in cluster.procedure_inventory: 30 | return 31 | 32 | cert_list = cluster.procedure_inventory["kubernetes"].get("cert-list") 33 | verify_all_is_absent_or_single(cert_list) 34 | 35 | 36 | def renew_apply(control_planes: NodeGroup) -> None: 37 | log = control_planes.cluster.log 38 | 39 | procedure = control_planes.cluster.procedure_inventory["kubernetes"] 40 | cert_list = procedure["cert-list"] 41 | 42 | for cert in cert_list: 43 | control_planes.sudo(f"kubeadm certs renew {cert}", pty=True) 44 | 45 | if "all" in cert_list or "admin.conf" in cert_list: 46 | # need to update cluster-admin config 47 | kubernetes.copy_admin_config(log, control_planes) 48 | 49 | # for some reason simple pod delete do not work for certs update - we need to delete containers themselves 50 | control_planes.call(kubernetes.components.restart_components, 51 | components=kubernetes.components.CONTROL_PLANE_COMPONENTS) 52 | 53 | 54 | def verify_all_is_absent_or_single(cert_list: List[str]) -> None: 55 | if "all" in cert_list and len(cert_list) > 1: 56 | raise Exception(f"Found 'all' in certs list, but it is not single: {cert_list}") 57 | -------------------------------------------------------------------------------- /kubemarine/kubernetes/daemonset.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from kubemarine.core.cluster import KubernetesCluster 16 | from kubemarine.kubernetes.object import KubernetesObject 17 | 18 | 19 | class DaemonSet(KubernetesObject): 20 | 21 | def __init__(self, cluster: KubernetesCluster, name: str = None, namespace: str = None, obj: dict = None) -> None: 22 | super().__init__(cluster, kind='DaemonSet', name=name, namespace=namespace, obj=obj) 23 | 24 | def is_actual_and_ready(self) -> bool: 25 | return self.is_ready() and self.is_up_to_date() 26 | 27 | def is_up_to_date(self) -> bool: 28 | desired_number_scheduled = self._obj.get('status', {}).get('desiredNumberScheduled') 29 | updated_number_scheduled = self._obj.get('status', {}).get('updatedNumberScheduled') 30 | return desired_number_scheduled is not None \ 31 | and updated_number_scheduled is not None \ 32 | and desired_number_scheduled == updated_number_scheduled 33 | 34 | def is_ready(self) -> bool: 35 | desired_number_scheduled = self._obj.get('status', {}).get('desiredNumberScheduled') 36 | number_ready = self._obj.get('status', {}).get('numberReady') 37 | return desired_number_scheduled is not None \ 38 | and number_ready is not None \ 39 | and desired_number_scheduled == number_ready 40 | 41 | def is_scheduled(self) -> bool: 42 | desired_number_scheduled = self._obj.get('status', {}).get('desiredNumberScheduled') 43 | current_number_scheduled = self._obj.get('status', {}).get('currentNumberScheduled') 44 | return desired_number_scheduled is not None \ 45 | and current_number_scheduled is not None \ 46 | and desired_number_scheduled == current_number_scheduled 47 | -------------------------------------------------------------------------------- /kubemarine/kubernetes/deployment.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from kubemarine.core.cluster import KubernetesCluster 16 | from kubemarine.kubernetes.object import KubernetesObject 17 | 18 | 19 | class Deployment(KubernetesObject): 20 | 21 | def __init__(self, cluster: KubernetesCluster, name: str = None, namespace: str = None, obj: dict = None) -> None: 22 | super().__init__(cluster, kind='Deployment', name=name, namespace=namespace, obj=obj) 23 | 24 | def is_actual_and_ready(self) -> bool: 25 | return self.is_ready() and self.is_up_to_date() 26 | 27 | def is_up_to_date(self) -> bool: 28 | desired_number_scheduled = self._obj.get('spec', {}).get('replicas') 29 | updated_number_scheduled = self._obj.get('status', {}).get('updatedReplicas') 30 | return desired_number_scheduled is not None \ 31 | and updated_number_scheduled is not None \ 32 | and desired_number_scheduled == updated_number_scheduled 33 | 34 | def is_ready(self) -> bool: 35 | desired_number_scheduled = self._obj.get('spec', {}).get('replicas') 36 | number_ready = self._obj.get('status', {}).get('readyReplicas') 37 | return desired_number_scheduled is not None \ 38 | and number_ready is not None \ 39 | and desired_number_scheduled == number_ready 40 | -------------------------------------------------------------------------------- /kubemarine/kubernetes/replicaset.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from kubemarine.core.cluster import KubernetesCluster 16 | from kubemarine.kubernetes.object import KubernetesObject 17 | 18 | 19 | class ReplicaSet(KubernetesObject): 20 | 21 | def __init__(self, cluster: KubernetesCluster, name: str = None, namespace: str = None, obj: dict = None) -> None: 22 | super().__init__(cluster, kind='ReplicaSet', name=name, namespace=namespace, obj=obj) 23 | 24 | def is_actual_and_ready(self) -> bool: 25 | return self.is_available() and self.is_fully_labeled() and self.is_ready() 26 | 27 | def is_ready(self) -> bool: 28 | desired_number_scheduled = self._obj.get('spec', {}).get('replicas') 29 | number_ready = self._obj.get('status', {}).get('readyReplicas') 30 | return desired_number_scheduled is not None \ 31 | and number_ready is not None \ 32 | and desired_number_scheduled == number_ready 33 | 34 | def is_available(self) -> bool: 35 | desired_number_scheduled = self._obj.get('spec', {}).get('replicas') 36 | available_number = self._obj.get('status', {}).get('availableReplicas') 37 | return desired_number_scheduled is not None \ 38 | and available_number is not None \ 39 | and desired_number_scheduled == available_number 40 | 41 | def is_fully_labeled(self) -> bool: 42 | desired_number_scheduled = self._obj.get('spec', {}).get('replicas') 43 | fully_labeled_number = self._obj.get('status', {}).get('fullyLabeledReplicas') 44 | return desired_number_scheduled is not None \ 45 | and fully_labeled_number is not None \ 46 | and desired_number_scheduled == fully_labeled_number 47 | -------------------------------------------------------------------------------- /kubemarine/kubernetes/statefulset.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from kubemarine.core.cluster import KubernetesCluster 16 | from kubemarine.kubernetes.object import KubernetesObject 17 | 18 | 19 | class StatefulSet(KubernetesObject): 20 | 21 | def __init__(self, cluster: KubernetesCluster, name: str = None, namespace: str = None, obj: dict = None) -> None: 22 | super().__init__(cluster, kind='StatefulSet', name=name, namespace=namespace, obj=obj) 23 | 24 | def is_actual_and_ready(self) -> bool: 25 | return self.is_updated() and self.is_ready() 26 | 27 | def is_ready(self) -> bool: 28 | desired_number = self._obj.get('spec', {}).get('replicas') 29 | ready_number = self._obj.get('status', {}).get('readyReplicas') 30 | return desired_number is not None \ 31 | and ready_number is not None \ 32 | and desired_number == ready_number 33 | 34 | def is_updated(self) -> bool: 35 | desired_number = self._obj.get('spec', {}).get('replicas') 36 | updated_number = self._obj.get('status', {}).get('updatedReplicas') 37 | return desired_number is not None \ 38 | and updated_number is not None \ 39 | and desired_number == updated_number 40 | 41 | def is_scheduled(self) -> bool: 42 | desired_number = self._obj.get('spec', {}).get('replicas') 43 | current_number = self._obj.get('status', {}).get('currentReplicas') 44 | return desired_number is not None \ 45 | and current_number is not None \ 46 | and desired_number == current_number 47 | -------------------------------------------------------------------------------- /kubemarine/patches/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """ 16 | All files and directories inside kubemarine/patches directory should participate only in patching mechanism, 17 | and relate to the current Kubemarine version. 18 | 19 | The whole directory is automatically cleared and reset after new version of Kubemarine is released. 20 | """ 21 | 22 | from typing import List 23 | 24 | from kubemarine.core.patch import Patch 25 | 26 | patches: List[Patch] = [ 27 | ] 28 | """ 29 | List of patches that is sorted according to the Patch.priority() before execution. 30 | Patches that have the same priority, are executed in the declared order. 31 | """ 32 | -------------------------------------------------------------------------------- /kubemarine/patches/software_upgrade.yaml: -------------------------------------------------------------------------------- 1 | # The file is managed by "scripts/thirdparties/sync.py". 2 | # It should still be manually changed to upgrade packages. 3 | # 4 | # Each software is mapped to the list of Kubernetes versions for which the upgrade is relevant. 5 | # Special case is for packages 'haproxy' and 'keepalived' 6 | # that have boolean flag if upgrade is necessary for all Kubernetes versions. 7 | # 8 | # The order of upgrade of defined by the implementation. 9 | 10 | thirdparties: 11 | calicoctl: [] 12 | crictl: [] 13 | packages: 14 | containerd: 15 | version_debian: [] 16 | containerdio: 17 | version_rhel: [] 18 | version_rhel8: [] 19 | version_rhel9: [] 20 | haproxy: 21 | version_rhel: false 22 | version_rhel8: false 23 | version_rhel9: false 24 | version_debian: false 25 | keepalived: 26 | version_rhel: false 27 | version_rhel8: false 28 | version_rhel9: false 29 | version_debian: false 30 | plugins: 31 | calico: [] 32 | nginx-ingress-controller: [] 33 | kubernetes-dashboard: [] 34 | local-path-provisioner: [] 35 | -------------------------------------------------------------------------------- /kubemarine/procedures/config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import argparse 16 | import json 17 | import sys 18 | from typing import List 19 | 20 | import yaml 21 | 22 | from kubemarine import plugins 23 | from kubemarine.core import static 24 | 25 | HELP_DESCRIPTION = """\ 26 | Print the supported k8s versions with the respective configurations of third-parties. 27 | 28 | How to use: 29 | 30 | """ 31 | 32 | 33 | def make_config() -> dict: 34 | kubernetes_versions: dict = {} 35 | for version, compatibility_map in static.KUBERNETES_VERSIONS['compatibility_map'].items(): 36 | kubernetes_version = kubernetes_versions.setdefault(version, {}) 37 | 38 | plugins_ = plugins.oob_plugins 39 | thirdparties_ = ['crictl'] 40 | 41 | for software, software_version in compatibility_map.items(): 42 | if software in plugins_: 43 | kubernetes_version.setdefault('plugins', {}) \ 44 | .setdefault(software, {})['version'] = software_version 45 | 46 | if software in thirdparties_: 47 | kubernetes_version.setdefault('thirdparties', {}) \ 48 | .setdefault(software, {})['version'] = software_version 49 | 50 | return {'kubernetes': kubernetes_versions} 51 | 52 | 53 | def print_config(cfg: dict, arguments: dict) -> None: 54 | # pylint: disable=bad-builtin 55 | 56 | format_ = arguments['output'] 57 | if format_ == 'yaml': 58 | print(yaml.safe_dump(cfg, sort_keys=False), end='') 59 | elif format_ == 'json': 60 | print(json.dumps(cfg, indent=4)) 61 | 62 | 63 | def create_context(cli_arguments: List[str] = None) -> dict: 64 | if cli_arguments is None: 65 | cli_arguments = sys.argv[1:] 66 | 67 | parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 68 | prog='config', 69 | description=HELP_DESCRIPTION) 70 | 71 | parser.add_argument('-o', '--output', 72 | choices=['yaml', 'json'], default='yaml', 73 | help='output format') 74 | 75 | arguments = vars(parser.parse_args(cli_arguments)) 76 | return {'config_arguments': arguments} 77 | 78 | 79 | def main(cli_arguments: List[str] = None) -> None: 80 | arguments = create_context(cli_arguments)['config_arguments'] 81 | cfg = make_config() 82 | print_config(cfg, arguments) 83 | 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /kubemarine/procedures/manage_pss.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2021-2022 NetCracker Technology Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | from collections import OrderedDict 18 | from typing import List 19 | 20 | from kubemarine import admission 21 | from kubemarine.core import flow 22 | 23 | tasks = OrderedDict({ 24 | "manage_pss": admission.manage_pss, 25 | "restart_pods": admission.restart_pods_task 26 | }) 27 | 28 | 29 | class PSSAction(flow.TasksAction): 30 | def __init__(self) -> None: 31 | super().__init__('manage pss', tasks, recreate_inventory=True) 32 | 33 | 34 | def create_context(cli_arguments: List[str] = None) -> dict: 35 | 36 | cli_help = ''' 37 | Script for managing pss on existing Kubernetes cluster. 38 | 39 | How to use: 40 | 41 | ''' 42 | 43 | parser = flow.new_procedure_parser(cli_help, tasks=tasks) 44 | context = flow.create_context(parser, cli_arguments, procedure='manage_pss') 45 | return context 46 | 47 | 48 | def main(cli_arguments: List[str] = None) -> None: 49 | context = create_context(cli_arguments) 50 | flow.ActionsFlow([PSSAction()]).run_flow(context) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /kubemarine/procedures/reboot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2021-2022 NetCracker Technology Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | from collections import OrderedDict 18 | from typing import List 19 | 20 | from kubemarine.core import flow 21 | from kubemarine.core.cluster import KubernetesCluster 22 | from kubemarine.procedures import install 23 | from kubemarine import system 24 | 25 | 26 | def reboot(cluster: KubernetesCluster) -> None: 27 | if cluster.context.get('initial_procedure') != 'reboot': 28 | raise ImportError('Invalid reboot.py usage, please use system.reboot_nodes') 29 | 30 | if not cluster.procedure_inventory.get("nodes"): 31 | cluster.log.verbose('No nodes defined in procedure: all nodes will be rebooted') 32 | else: 33 | cluster.log.verbose('There are nodes defined in procedure: only defined will be rebooted') 34 | 35 | nodes = [] 36 | 37 | cluster.log.verbose('The following nodes will be rebooted:') 38 | for node in cluster.procedure_inventory.get("nodes", cluster.inventory['nodes']): 39 | nodes.append(node['name']) 40 | cluster.log.verbose(' - ' + node['name']) 41 | 42 | system.reboot_group(cluster.make_group_from_nodes(nodes), 43 | try_graceful=cluster.procedure_inventory.get("graceful_reboot")) 44 | 45 | 46 | tasks = OrderedDict({ 47 | "reboot": reboot, 48 | "overview": install.overview, 49 | }) 50 | 51 | 52 | class RebootAction(flow.TasksAction): 53 | def __init__(self) -> None: 54 | super().__init__('reboot', tasks) 55 | 56 | 57 | def create_context(cli_arguments: List[str] = None) -> dict: 58 | cli_help = ''' 59 | Script for Kubernetes nodes graceful rebooting. 60 | 61 | How to use: 62 | 63 | ''' 64 | 65 | parser = flow.new_procedure_parser(cli_help, optional_config=True, tasks=tasks) 66 | 67 | context = flow.create_context(parser, cli_arguments, procedure='reboot') 68 | return context 69 | 70 | 71 | def main(cli_arguments: List[str] = None) -> None: 72 | context = create_context(cli_arguments) 73 | flow.ActionsFlow([RebootAction()]).run_flow(context) 74 | 75 | 76 | if __name__ == '__main__': 77 | main() 78 | -------------------------------------------------------------------------------- /kubemarine/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/kubemarine/py.typed -------------------------------------------------------------------------------- /kubemarine/resources/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/resources/configurations/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/resources/configurations/compatibility/internal/packages.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is partially generated and maintained by "scripts/thirdparties/sync.py" 2 | # 3 | # If new Kubernetes version is added, the compatibility mapping is taken from the previous Kubernetes versions. 4 | # The developer should manually change the required package versions if necessary. 5 | # 6 | # After any change, kubemarine/patches/software_upgrade.yaml should also be manually changed. 7 | containerd: 8 | v1.29.1: 9 | version_debian: 1.7.* 10 | v1.29.4: 11 | version_debian: 1.7.* 12 | v1.29.7: 13 | version_debian: 1.7.* 14 | v1.29.10: 15 | version_debian: 1.7.* 16 | v1.30.1: 17 | version_debian: 1.7.* 18 | v1.30.3: 19 | version_debian: 1.7.* 20 | v1.30.10: 21 | version_debian: 1.7.* 22 | v1.31.1: 23 | version_debian: 1.7.* 24 | v1.31.6: 25 | version_debian: 1.7.* 26 | v1.32.0: 27 | version_debian: 1.7.* 28 | v1.32.2: 29 | version_debian: 1.7.* 30 | v1.33.0: 31 | version_debian: 1.7.* 32 | containerdio: 33 | v1.29.1: 34 | version_rhel: 1.6* 35 | version_rhel8: 1.6* 36 | version_rhel9: 1.6* 37 | v1.29.4: 38 | version_rhel: 1.6* 39 | version_rhel8: 1.6* 40 | version_rhel9: 1.6* 41 | v1.29.7: 42 | version_rhel: 1.6* 43 | version_rhel8: 1.6* 44 | version_rhel9: 1.6* 45 | v1.29.10: 46 | version_rhel: 1.6* 47 | version_rhel8: 1.6* 48 | version_rhel9: 1.6* 49 | v1.30.1: 50 | version_rhel: 1.6* 51 | version_rhel8: 1.6* 52 | version_rhel9: 1.6* 53 | v1.30.3: 54 | version_rhel: 1.6* 55 | version_rhel8: 1.6* 56 | version_rhel9: 1.6* 57 | v1.30.10: 58 | version_rhel: 1.6* 59 | version_rhel8: 1.6* 60 | version_rhel9: 1.6* 61 | v1.31.1: 62 | version_rhel: 1.6* 63 | version_rhel8: 1.6* 64 | version_rhel9: 1.6* 65 | v1.31.6: 66 | version_rhel: 1.6* 67 | version_rhel8: 1.6* 68 | version_rhel9: 1.6* 69 | v1.32.0: 70 | version_rhel: 1.6* 71 | version_rhel8: 1.6* 72 | version_rhel9: 1.6* 73 | v1.32.2: 74 | version_rhel: 1.6* 75 | version_rhel8: 1.6* 76 | version_rhel9: 1.6* 77 | v1.33.0: 78 | version_rhel: 1.6* 79 | version_rhel8: 1.6* 80 | version_rhel9: 1.6* 81 | haproxy: 82 | version_rhel: 1.8* 83 | version_rhel8: 1.8* 84 | version_rhel9: 2.4* 85 | version_debian: 2.* 86 | keepalived: 87 | version_rhel: 1.3* 88 | version_rhel8: 2.1* 89 | version_rhel9: 2.2* 90 | version_debian: 1:2.* 91 | -------------------------------------------------------------------------------- /kubemarine/resources/configurations/compatibility/kubernetes_versions.yaml: -------------------------------------------------------------------------------- 1 | # This section can be changed manually, but it is also synchronized automatically with the 'compatibility_map' section below. 2 | kubernetes_versions: 3 | v1.29: 4 | supported: true 5 | v1.30: 6 | supported: true 7 | v1.31: 8 | supported: true 9 | v1.32: 10 | supported: true 11 | v1.33: 12 | supported: true 13 | compatibility_map: 14 | # This section should be changed manually. 15 | v1.29.1: 16 | calico: v3.29.1 17 | nginx-ingress-controller: v1.11.6 18 | kubernetes-dashboard: v2.7.0 19 | local-path-provisioner: v0.0.26 20 | crictl: v1.29.0 21 | v1.29.4: 22 | calico: v3.29.1 23 | nginx-ingress-controller: v1.11.6 24 | kubernetes-dashboard: v2.7.0 25 | local-path-provisioner: v0.0.26 26 | crictl: v1.30.0 27 | v1.29.7: 28 | calico: v3.29.1 29 | nginx-ingress-controller: v1.11.6 30 | kubernetes-dashboard: v2.7.0 31 | local-path-provisioner: v0.0.27 32 | crictl: v1.30.0 33 | v1.29.10: 34 | calico: v3.29.1 35 | nginx-ingress-controller: v1.11.6 36 | kubernetes-dashboard: v2.7.0 37 | local-path-provisioner: v0.0.27 38 | crictl: v1.30.0 39 | v1.30.1: 40 | calico: v3.29.1 41 | nginx-ingress-controller: v1.11.6 42 | kubernetes-dashboard: v2.7.0 43 | local-path-provisioner: v0.0.26 44 | crictl: v1.30.0 45 | v1.30.3: 46 | calico: v3.29.1 47 | nginx-ingress-controller: v1.11.6 48 | kubernetes-dashboard: v2.7.0 49 | local-path-provisioner: v0.0.27 50 | crictl: v1.30.0 51 | v1.30.10: 52 | calico: v3.29.1 53 | nginx-ingress-controller: v1.11.6 54 | kubernetes-dashboard: v2.7.0 55 | local-path-provisioner: v0.0.27 56 | crictl: v1.30.0 57 | v1.31.1: 58 | calico: v3.29.1 59 | nginx-ingress-controller: v1.11.6 60 | kubernetes-dashboard: v2.7.0 61 | local-path-provisioner: v0.0.27 62 | crictl: v1.30.0 63 | v1.31.6: 64 | calico: v3.29.1 65 | nginx-ingress-controller: v1.11.6 66 | kubernetes-dashboard: v2.7.0 67 | local-path-provisioner: v0.0.27 68 | crictl: v1.30.0 69 | v1.32.0: 70 | calico: v3.29.1 71 | nginx-ingress-controller: v1.11.6 72 | kubernetes-dashboard: v2.7.0 73 | local-path-provisioner: v0.0.27 74 | crictl: v1.32.0 75 | v1.32.2: 76 | calico: v3.29.1 77 | nginx-ingress-controller: v1.11.6 78 | kubernetes-dashboard: v2.7.0 79 | local-path-provisioner: v0.0.27 80 | crictl: v1.32.0 81 | v1.33.0: 82 | calico: v3.29.1 83 | nginx-ingress-controller: v1.11.6 84 | kubernetes-dashboard: v2.7.0 85 | local-path-provisioner: v0.0.31 86 | crictl: v1.33.0 87 | # After any change, please run scripts/thirdparties/sync.py 88 | 89 | # The following optional keys are supported in addition to the 5 required software keys: 90 | #: 91 | # webhook: 92 | # metrics-scraper: 93 | # busybox: 94 | -------------------------------------------------------------------------------- /kubemarine/resources/drop_ins/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/resources/drop_ins/haproxy.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | Restart=always 3 | -------------------------------------------------------------------------------- /kubemarine/resources/drop_ins/keepalived.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | Restart=always 3 | -------------------------------------------------------------------------------- /kubemarine/resources/etalons/patches/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """ 16 | All files and directories inside kubemarine/patches directory should participate only in patching mechanism, 17 | and relate to the current Kubemarine version. 18 | 19 | The whole directory is automatically cleared and reset after new version of Kubemarine is released. 20 | """ 21 | 22 | from typing import List 23 | 24 | from kubemarine.core.patch import Patch 25 | 26 | patches: List[Patch] = [ 27 | ] 28 | """ 29 | List of patches that is sorted according to the Patch.priority() before execution. 30 | Patches that have the same priority, are executed in the declared order. 31 | """ 32 | -------------------------------------------------------------------------------- /kubemarine/resources/etalons/patches/software_upgrade.yaml: -------------------------------------------------------------------------------- 1 | # The file is managed by "scripts/thirdparties/sync.py". 2 | # It should still be manually changed to upgrade packages. 3 | # 4 | # Each software is mapped to the list of Kubernetes versions for which the upgrade is relevant. 5 | # Special case is for packages 'haproxy' and 'keepalived' 6 | # that have boolean flag if upgrade is necessary for all Kubernetes versions. 7 | # 8 | # The order of upgrade of defined by the implementation. 9 | 10 | thirdparties: 11 | calicoctl: [] 12 | crictl: [] 13 | packages: 14 | containerd: 15 | version_debian: [] 16 | containerdio: 17 | version_rhel: [] 18 | version_rhel8: [] 19 | version_rhel9: [] 20 | haproxy: 21 | version_rhel: false 22 | version_rhel8: false 23 | version_rhel9: false 24 | version_debian: false 25 | keepalived: 26 | version_rhel: false 27 | version_rhel8: false 28 | version_rhel9: false 29 | version_debian: false 30 | plugins: 31 | calico: [] 32 | nginx-ingress-controller: [] 33 | kubernetes-dashboard: [] 34 | local-path-provisioner: [] 35 | -------------------------------------------------------------------------------- /kubemarine/resources/reports/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/resources/reports/check_report.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 14px; 3 | font-family: Arial; 4 | } 5 | table { 6 | position: absolute; 7 | width: 1000px; 8 | left: 50%; 9 | margin-left: -500px; 10 | margin-top: 100px; 11 | border:none; 12 | border-collapse: collapse; 13 | font-size: 14px; 14 | } 15 | table tr { 16 | height: 40px; 17 | } 18 | table > tbody > tr:nth-child(odd) { 19 | background: #FAFAFA; 20 | } 21 | table > thead > tr { 22 | height: 60px; 23 | opacity: .5; 24 | } 25 | table > tbody > tr > td:nth-child(2) > div, #stats > div { 26 | height: 26px; 27 | color: #fff; 28 | text-align: center; 29 | line-height: 27px; 30 | text-transform: uppercase; 31 | font-size: 10px; 32 | border-radius: 8px; 33 | padding: 0 1px; 34 | margin: 0 10px 0 0; 35 | } 36 | table > tbody > tr.ok > td:nth-child(2) > div, #stats > div.succeeded{ 37 | background: #4CAF50; 38 | } 39 | table > tbody > tr.fail > td:nth-child(2) > div, #stats > div.failed { 40 | background: #f44336; 41 | } 42 | table > tbody > tr.warning > td:nth-child(2) > div, #stats > div.warned { 43 | background: #FF9800; 44 | } 45 | table > tbody > tr.exception > td:nth-child(2) > div, #stats > div.excepted { 46 | background: #607D8B; 47 | } 48 | h1 { 49 | width: 1000px; 50 | position: absolute; 51 | left: 50%; 52 | margin-left: -500px; 53 | margin-top: 50px; 54 | } 55 | #date { 56 | position: absolute; 57 | margin-top: 30px; 58 | left: 50%; 59 | width: 1000px; 60 | margin-left: -500px; 61 | } 62 | #stats { 63 | position: absolute; 64 | margin-top: 50px; 65 | margin-left: -500px; 66 | left: 50%; 67 | width: 1000px; 68 | } 69 | #stats > div { 70 | float: right; 71 | padding: 2px 10px; 72 | margin: 0 0 0 10px; 73 | } 74 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/add_node.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "nodes": { 6 | "type": "array", 7 | "description": "New nodes in the same format as that of the installation procedure.", 8 | "minItems": 1, 9 | "items": { 10 | "$ref": "definitions/node.json" 11 | } 12 | }, 13 | "prepull_group_size": {"$ref": "definitions/procedures.json#/definitions/PrepullGroupSize"} 14 | }, 15 | "required": ["nodes"], 16 | "additionalProperties": false 17 | } 18 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/backup.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "backup_location": { 6 | "type": "string", 7 | "default": "backup.tar.gz", 8 | "description": "Target location of the backup archive." 9 | }, 10 | "backup_plan": { 11 | "type": "object", 12 | "description": "Backup procedure configuration.", 13 | "properties": { 14 | "etcd": { 15 | "type": "object", 16 | "description": "Custom parameters for the ETCD snapshot creation task.", 17 | "properties": { 18 | "source_node": { 19 | "$ref": "definitions/common/node_ref.json#/definitions/Name", 20 | "description": "The name of the node to create a snapshot from. The node must be a control-plane and have an ETCD data located on it." 21 | } 22 | }, 23 | "additionalProperties": false 24 | }, 25 | "nodes": { 26 | "type": "object", 27 | "description": "Add additional files for backup, or disable the default ones. Keys are the full file or directory paths. Values are the enable or exclude indicators.", 28 | "additionalProperties": { 29 | "type": "boolean" 30 | } 31 | }, 32 | "kubernetes": { 33 | "type": "object", 34 | "description": "Specify resources for export if you need only a restricted set of resources.", 35 | "properties": { 36 | "namespaced_resources": { 37 | "type": "object", 38 | "description": "Namespaced resources to export.", 39 | "properties": { 40 | "namespaces": { 41 | "$ref": "#/definitions/ListOrEverything", 42 | "description": "Namespaces from which to export. Specify 'all' to export everything." 43 | }, 44 | "resources": { 45 | "$ref": "#/definitions/ListOrEverything", 46 | "description": "Full names of the resources to be exported. Specify 'all' to export everything." 47 | } 48 | }, 49 | "additionalProperties": false 50 | }, 51 | "nonnamespaced_resources": { 52 | "$ref": "#/definitions/ListOrEverything", 53 | "description": "Full names of the non-namespaced resources to be exported. Specify 'all' to export everything." 54 | } 55 | }, 56 | "additionalProperties": false 57 | } 58 | }, 59 | "additionalProperties": false 60 | } 61 | }, 62 | "additionalProperties": false, 63 | "definitions": { 64 | "ListOrEverything": { 65 | "oneOf": [ 66 | {"type": "string", "enum": ["all"], "default": "all"}, 67 | {"$ref": "definitions/common/utils.json#/definitions/SetOfStrings"} 68 | ] 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/cert_renew.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "nginx-ingress-controller": { 6 | "$ref": "definitions/plugins/nginx-ingress-controller.json#/definitions/DefaultCertificate" 7 | }, 8 | "calico": { 9 | "type": "object", 10 | "description": "Update internal Calico certificates.", 11 | "properties": { 12 | "apiserver": { 13 | "type": "object", 14 | "description": "Manage renew process of Calico API server certificate.", 15 | "properties": { 16 | "renew": { 17 | "type": "boolean", 18 | "enum": [true] 19 | } 20 | }, 21 | "required": ["renew"], 22 | "additionalProperties": false 23 | } 24 | }, 25 | "required": ["apiserver"], 26 | "additionalProperties": false 27 | }, 28 | "kubernetes": { 29 | "type": "object", 30 | "description": "Update internal Kubernetes certificates.", 31 | "properties": { 32 | "cert-list": { 33 | "type": "array", 34 | "description": "List with particular certificates, or 'all' if all possible certificates should be updated.", 35 | "items": { 36 | "enum": [ 37 | "all", 38 | "apiserver", "apiserver-etcd-client", "apiserver-kubelet-client", 39 | "etcd-healthcheck-client", "etcd-peer", "etcd-server", 40 | "admin.conf", "super-admin.conf", 41 | "controller-manager.conf", "scheduler.conf", 42 | "front-proxy-client" 43 | ] 44 | }, 45 | "minItems": 1, 46 | "uniqueItems": true 47 | } 48 | }, 49 | "additionalProperties": false 50 | } 51 | }, 52 | "additionalProperties": false 53 | } 54 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/check_paas.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "geo-monitor": { 6 | "type": "object", 7 | "properties": { 8 | "namespace": { 9 | "type": "string" 10 | }, 11 | "service": { 12 | "type": "string" 13 | } 14 | }, 15 | "required": ["namespace", "service"], 16 | "additionalProperties": false 17 | } 18 | }, 19 | "additionalProperties": false 20 | } 21 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/common/node_ref.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "definitions": { 4 | "Role": { 5 | "enum": ["worker", "control-plane", "balancer"] 6 | }, 7 | "Kubernetes": { 8 | "enum": ["worker", "control-plane"] 9 | }, 10 | "ControlPlane": { 11 | "enum": ["control-plane"] 12 | }, 13 | "Roles": { 14 | "type": "array", 15 | "items": { 16 | "$ref": "#/definitions/Role" 17 | }, 18 | "uniqueItems": true, 19 | "minItems": 1 20 | }, 21 | "KubernetesRoles": { 22 | "type": "array", 23 | "items": { 24 | "$ref": "#/definitions/Kubernetes" 25 | }, 26 | "uniqueItems": true, 27 | "minItems": 1 28 | }, 29 | "ControlPlanes": { 30 | "type": "array", 31 | "items": { 32 | "$ref": "#/definitions/ControlPlane" 33 | }, 34 | "uniqueItems": true, 35 | "minItems": 1 36 | }, 37 | "Name": { 38 | "type": "string" 39 | }, 40 | "Names": { 41 | "type": "array", 42 | "items": { 43 | "$ref": "#/definitions/Name" 44 | }, 45 | "uniqueItems": true, 46 | "minItems": 1 47 | }, 48 | "OneOfNodesGroupsSpec": { 49 | "type": "object", 50 | "oneOf": [ 51 | {"$ref": "#/definitions/GroupsSpec"}, 52 | {"$ref": "#/definitions/NodesSpec"} 53 | ] 54 | }, 55 | "AnyOfNodesGroupsSpec": { 56 | "type": "object", 57 | "anyOf": [ 58 | {"$ref": "#/definitions/GroupsSpec"}, 59 | {"$ref": "#/definitions/NodesSpec"} 60 | ] 61 | }, 62 | "GroupsSpec": { 63 | "type": "object", 64 | "properties": { 65 | "groups": { 66 | "type": "array" 67 | } 68 | }, 69 | "required": ["groups"] 70 | }, 71 | "NodesSpec": { 72 | "type": "object", 73 | "properties": { 74 | "nodes": { 75 | "type": "array" 76 | } 77 | }, 78 | "required": ["nodes"] 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/common/utils.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "definitions": { 4 | "ArrayOfStrings": { 5 | "type": "array", 6 | "items": { 7 | "type": "string" 8 | } 9 | }, 10 | "NonEmptyArrayOfStrings": { 11 | "type": "array", 12 | "items": { 13 | "type": "string" 14 | }, 15 | "minItems": 1 16 | }, 17 | "SetOfStrings": { 18 | "type": "array", 19 | "items": { 20 | "type": "string" 21 | }, 22 | "uniqueItems": true 23 | }, 24 | "NonEmptySetOfStrings": { 25 | "type": "array", 26 | "items": { 27 | "type": "string" 28 | }, 29 | "uniqueItems": true, 30 | "minItems": 1 31 | }, 32 | "ArrayOfObjects": { 33 | "type": "array", 34 | "items": { 35 | "type": "object" 36 | } 37 | }, 38 | "NonEmptyArrayOfObjects": { 39 | "type": "array", 40 | "items": { 41 | "type": "object" 42 | }, 43 | "minItems": 1 44 | }, 45 | "MergeableArrayOfObjects": { 46 | "type": "array", 47 | "items": { 48 | "oneOf": [ 49 | {"type": "object", "propertyNames": {"not": {"enum": ["<<"]}}}, 50 | {"$ref": "#/definitions/ListMergingSymbol"} 51 | ] 52 | } 53 | }, 54 | "MergeableSetOfStrings": { 55 | "type": "array", 56 | "items": { 57 | "oneOf": [ 58 | {"type": "string"}, 59 | {"$ref": "../common/utils.json#/definitions/ListMergingSymbol"} 60 | ] 61 | }, 62 | "uniqueItems": true 63 | }, 64 | "ListMergingDefinition": { 65 | "enum": ["replace", "merge"], 66 | "default": "replace", 67 | "description": "Specify '<<' instead of <<. List merging strategy." 68 | }, 69 | "ListMergingSymbol": { 70 | "type": "object", 71 | "properties": { 72 | "<<": {"$ref": "#/definitions/ListMergingDefinition"} 73 | }, 74 | "required": ["<<"], 75 | "additionalProperties": false 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/gateway_node.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "allOf": [ 5 | {"$ref": "node_defaults.json#/definitions/SSHAccessCommonProperties"}, 6 | {"$ref": "node_defaults.json#/definitions/OneOfKeyfilePasswordSpec"} 7 | ], 8 | "properties": { 9 | "name": { 10 | "type": "string", 11 | "description": "Gateway node name" 12 | }, 13 | "address": { 14 | "type": "string", 15 | "description": "Gateway node's IP or hostname address for connection" 16 | } 17 | }, 18 | "required": ["name", "address", "username"], 19 | "propertyNames": { 20 | "anyOf": [ 21 | {"$ref": "node_defaults.json#/definitions/SSHAccessCommonPropertyNames"}, 22 | {"enum": ["name", "address"]} 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/node.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "allOf": [{"$ref": "#/definitions/Properties"}], 5 | "required": ["internal_address", "roles"], 6 | "propertyNames": { 7 | "$ref": "#/definitions/PropertyNames" 8 | }, 9 | "definitions": { 10 | "AccessProperties": { 11 | "allOf": [{"$ref": "node_defaults.json#/definitions/CommonNodeProperties"}], 12 | "properties": { 13 | "name": { 14 | "$ref": "common/node_ref.json#/definitions/Name", 15 | "description": "Cluster member name. If omitted, KubeMarine will calculate the name by the member role and position in the inventory." 16 | }, 17 | "address": { 18 | "type": "string", 19 | "description": "External node's IP-address" 20 | }, 21 | "internal_address": { 22 | "type": "string", 23 | "description": "Internal node's IP-address" 24 | }, 25 | "connect_to": {"type": "string"} 26 | } 27 | }, 28 | "AccessPropertyNames": { 29 | "anyOf": [ 30 | {"$ref": "node_defaults.json#/definitions/CommonNodePropertyNames"}, 31 | {"enum": ["name", "address", "internal_address", "connect_to"]} 32 | ] 33 | }, 34 | "Properties": { 35 | "allOf": [{"$ref": "#/definitions/AccessProperties"}], 36 | "properties": { 37 | "roles": { 38 | "$ref": "common/node_ref.json#/definitions/Roles", 39 | "description": "Cluster member roles" 40 | }, 41 | "control_endpoint": { 42 | "type": "boolean", 43 | "default": false, 44 | "description": "Parameter to help the algorithm in choosing which address to take as the control_plain" 45 | } 46 | } 47 | }, 48 | "PropertyNames": { 49 | "anyOf": [ 50 | {"$ref": "#/definitions/AccessPropertyNames"}, 51 | {"enum": ["roles", "control_endpoint"]} 52 | ] 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/patch.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "allOf": [ 4 | {"$ref": "common/node_ref.json#/definitions/AnyOfNodesGroupsSpec"}, 5 | {"$ref": "#/definitions/Patch"} 6 | ], 7 | "definitions": { 8 | "Patch": { 9 | "type": "object", 10 | "properties": { 11 | "groups": {"$ref": "#/definitions/PatchGroups"}, 12 | "nodes": {"$ref": "#/definitions/PatchNodes"}, 13 | "services": { 14 | "type": "object", 15 | "description": "Configure settings of different services", 16 | "properties": { 17 | "sysctl": { 18 | "$ref": "services/sysctl.json", 19 | "description": "Manage the Linux Kernel parameters for the specified nodes in a patch" 20 | } 21 | }, 22 | "additionalProperties": false 23 | } 24 | }, 25 | "additionalProperties": false 26 | }, 27 | "PatchGroups": { 28 | "allOf": [{"$ref": "common/node_ref.json#/definitions/Roles"}], 29 | "default": ["worker", "control-plane", "balancer"], 30 | "description": "The list of group names to apply the patch to" 31 | }, 32 | "PatchNodes": { 33 | "allOf": [{"$ref": "common/node_ref.json#/definitions/Names"}], 34 | "description": "The list of node names to apply the patch to" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugin_defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Describe parameters that are to be applied by default to each record in the Plugins section", 5 | "properties": { 6 | "installation": { 7 | "type": "object", 8 | "description": "The section describes the plugins installation process", 9 | "allOf": [{"$ref": "plugins/installation.json#/definitions/DefaultProperties"}], 10 | "propertyNames": { 11 | "$ref": "plugins/installation.json#/definitions/DefaultPropertyNames" 12 | } 13 | } 14 | }, 15 | "additionalProperties": false 16 | } 17 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Configure the parameters of the plugins, as well as register your own plugins", 5 | "properties": { 6 | "calico": { 7 | "$ref": "plugins/calico.json" 8 | }, 9 | "nginx-ingress-controller": { 10 | "$ref": "plugins/nginx-ingress-controller.json" 11 | }, 12 | "kubernetes-dashboard": { 13 | "$ref": "plugins/kubernetes-dashboard.json" 14 | }, 15 | "local-path-provisioner": { 16 | "$ref": "plugins/local-path-provisioner.json" 17 | } 18 | }, 19 | "additionalProperties": { 20 | "$ref": "plugins/generic_plugin.json" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/generic_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Name (identifier) of the custom plugin", 5 | "allOf": [{"$ref": "#/definitions/Properties"}], 6 | "definitions": { 7 | "Properties": { 8 | "properties": { 9 | "install": { 10 | "type": ["string", "boolean"], 11 | "default": false, 12 | "description": "Specify if the plugin should be installed" 13 | }, 14 | "installation": { 15 | "$ref": "installation.json", 16 | "description": "The section describes the plugin installation process" 17 | } 18 | } 19 | }, 20 | "PropertyNames": { 21 | "enum": ["install", "installation"] 22 | }, 23 | "CustomTolerations": { 24 | "$ref": "../common/utils.json#/definitions/NonEmptyArrayOfObjects", 25 | "description": "Set custom tolerations for the plugin in order to influence pods scheduling for the plugin" 26 | }, 27 | "CommonNodeSelector": { 28 | "type": "object", 29 | "description": "Set custom nodeSelectors for the plugin in order to influence pods scheduling for the plugin", 30 | "properties": { 31 | "kubernetes.io/os": {"type": "string", "default": "linux"} 32 | } 33 | }, 34 | "RequestsLimitsForContainer": { 35 | "type": "object", 36 | "description": "Set custom requests/limits for the plugin container", 37 | "definitions": { 38 | "ValuesForMemoryCpuStorage": { 39 | "type": "object", 40 | "description": "Set memory, cpu and storage values for requests/limits", 41 | "properties": { 42 | "memory": {"type": ["string", "integer"]}, 43 | "cpu": {"type": ["string", "integer"]} 44 | }, 45 | "additionalProperties": false 46 | } 47 | }, 48 | "properties": { 49 | "limits": { 50 | "$ref": "#/definitions/RequestsLimitsForContainer/definitions/ValuesForMemoryCpuStorage" 51 | }, 52 | "requests": { 53 | "$ref": "#/definitions/RequestsLimitsForContainer/definitions/ValuesForMemoryCpuStorage" 54 | } 55 | }, 56 | "additionalProperties": false 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "allOf": [{"$ref": "#/definitions/DefaultProperties"}], 5 | "properties": { 6 | "priority": { 7 | "type": "integer", 8 | "description": "Parameter that defines the installation order of the plugin relative to the other plugins" 9 | }, 10 | "procedures": { 11 | "type": "array", 12 | "description": "Installation procedures to perform during the installation of the plugin", 13 | "items": { 14 | "type": "object", 15 | "properties": { 16 | "template": {"$ref": "installation/template.json"}, 17 | "config": {"$ref": "installation/config.json"}, 18 | "expect": {"$ref": "installation/expect.json"}, 19 | "python": {"$ref": "installation/python.json"}, 20 | "shell": {"$ref": "installation/shell.json"}, 21 | "ansible": {"$ref": "installation/ansible.json"}, 22 | "helm": {"$ref": "installation/helm.json"}, 23 | "thirdparty": { 24 | "type": "string", 25 | "description": "Trigger specific thirdparty installation. This thirdparty must be configured in the thirdparties section." 26 | }, 27 | "<<": {"$ref": "../common/utils.json#/definitions/ListMergingDefinition"} 28 | }, 29 | "minProperties": 1, 30 | "additionalProperties": false 31 | }, 32 | "minItems": 1 33 | } 34 | }, 35 | "propertyNames": { 36 | "anyOf": [ 37 | {"$ref": "#/definitions/DefaultPropertyNames"}, 38 | {"enum": ["priority", "procedures"]} 39 | ] 40 | }, 41 | "definitions": { 42 | "DefaultProperties": { 43 | "properties": { 44 | "registry": { 45 | "type": "string", 46 | "description": "The plugin(s) container's images are loaded from this registry" 47 | } 48 | } 49 | }, 50 | "DefaultPropertyNames": { 51 | "enum": ["registry"] 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation/ansible.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "description": "Directly execute Ansible playbooks. Can be either a local path to the playbook or a dictionary with the extra parameters.", 4 | "oneOf": [ 5 | {"type": "string", "minLength": 1}, 6 | { 7 | "type": "object", 8 | "properties": { 9 | "playbook": { 10 | "type": "string", 11 | "minLength": 1, 12 | "description": "A local path to a playbook to be executed" 13 | }, 14 | "vars": { 15 | "type": "object", 16 | "description": "Additional variables, overriding variables from Ansible inventory. They are passed as --extra-vars in CLI." 17 | }, 18 | "become": { 19 | "type": "boolean", 20 | "default": false, 21 | "description": "Privilege escalation switch. Enables -b argument." 22 | }, 23 | "groups": { 24 | "$ref": "../../common/node_ref.json#/definitions/Roles", 25 | "description": "Targeted list of groups, passed to Ansible as --limit argument" 26 | }, 27 | "nodes": { 28 | "$ref": "../../common/node_ref.json#/definitions/Names", 29 | "description": "Targeted list of nodes, passed to Ansible as --limit argument" 30 | } 31 | }, 32 | "required": ["playbook"], 33 | "additionalProperties": false 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "description": "An alias for template that allows you not to render the contents of the files", 4 | "oneOf": [ 5 | {"type": "string"}, 6 | { 7 | "type": "object", 8 | "allOf": [{"$ref": "template.json#/definitions/Properties"}], 9 | "properties": { 10 | "do_render": { 11 | "type": "boolean", 12 | "default": true, 13 | "description": "Allows you not to render the contents of the file" 14 | } 15 | }, 16 | "required": ["source"], 17 | "propertyNames": { 18 | "anyOf": [ 19 | {"$ref": "template.json#/definitions/PropertyNames"}, 20 | {"enum": ["do_render"]} 21 | ] 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation/helm.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "You can install or upgrade HELM chart on the Kubernetes cluster", 5 | "properties": { 6 | "chart_path": { 7 | "type": "string", 8 | "minLength": 1, 9 | "description": "The path on local host to the Helm chart. The URL link to chart archive is also supported." 10 | }, 11 | "values": { 12 | "type": "object", 13 | "description": "YAML formatted values for the chart that override values from the values.yaml file from the provided chart. The values from this parameter also override the values from the 'values_file' parameter." 14 | }, 15 | "values_file": { 16 | "type": "string", 17 | "description": "The path on local host to the file with YAML formatted values for the chart that override values from the values.yaml file from the provided chart." 18 | }, 19 | "release": { 20 | "type": "string", 21 | "description": "The target Helm release. It is equal to the chart name by default." 22 | }, 23 | "namespace": { 24 | "type": "string", 25 | "default": "default", 26 | "description": "The cloud namespace where the chart should be installed" 27 | } 28 | }, 29 | "required": ["chart_path"], 30 | "additionalProperties": false 31 | } 32 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation/python.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Directly call the Python 3 code", 5 | "properties": { 6 | "module": { 7 | "type": "string", 8 | "description": "The absolute path on local host to the Python 3 module to be loaded" 9 | }, 10 | "method": { 11 | "type": "string", 12 | "description": "The name of the method to call" 13 | }, 14 | "arguments": { 15 | "type": "object", 16 | "description": "Key-value map, which should be applied as kwargs to the requested method" 17 | } 18 | }, 19 | "required": ["module", "method"], 20 | "additionalProperties": false 21 | } 22 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation/shell.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "description": "Execute shell code on remote hosts. Can be either a command string or a dictionary with the extra parameters.", 4 | "oneOf": [ 5 | {"type": "string", "minLength": 1}, 6 | { 7 | "type": "object", 8 | "properties": { 9 | "command": { 10 | "description": "A shell command(s) to be executed on remote hosts. If the list of commands is provided, they will be joint with '&&'.", 11 | "oneOf": [ 12 | {"type": "string", "minLength": 1}, 13 | { 14 | "type": "array", 15 | "items": {"type": "string", "minLength": 1}, 16 | "minItems": 1 17 | } 18 | ] 19 | }, 20 | "sudo": { 21 | "type": "boolean", 22 | "default": false, 23 | "description": "Switch for the command execution from the sudoer" 24 | }, 25 | "groups": { 26 | "$ref": "../../common/node_ref.json#/definitions/Roles", 27 | "description": "List of groups on which the shell command should be executed" 28 | }, 29 | "nodes": { 30 | "$ref": "../../common/node_ref.json#/definitions/Names", 31 | "description": "List of nodes on which the shell command should be executed" 32 | }, 33 | "out_vars": { 34 | "type": "array", 35 | "description": "List of ENV variables to export and save for later use", 36 | "items": { 37 | "type": "object", 38 | "properties": { 39 | "name": { 40 | "type": "string" 41 | }, 42 | "save_as": { 43 | "type": "string" 44 | } 45 | }, 46 | "required": ["name"], 47 | "additionalProperties": false 48 | } 49 | }, 50 | "in_vars": { 51 | "type": "array", 52 | "description": "List of ENV variables to import before command execution", 53 | "items": { 54 | "type": "object", 55 | "properties": { 56 | "name": { 57 | "type": "string" 58 | }, 59 | "value": { 60 | "type": "string" 61 | } 62 | }, 63 | "required": ["name"], 64 | "additionalProperties": false 65 | } 66 | } 67 | }, 68 | "required": ["command"], 69 | "additionalProperties": false 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/installation/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "description": "Compile the Jinja2 template file, upload to remote hosts, and apply it. Can be either a local path to file or a dictionary with the extra parameters.", 4 | "oneOf": [ 5 | {"type": "string"}, 6 | { 7 | "type": "object", 8 | "allOf": [{"$ref": "#/definitions/Properties"}], 9 | "required": ["source"], 10 | "propertyNames": { 11 | "$ref": "#/definitions/PropertyNames" 12 | } 13 | } 14 | ], 15 | "definitions": { 16 | "Properties": { 17 | "properties": { 18 | "source": { 19 | "type": "string", 20 | "description": "The local path to the source Jinja2 template file. It is compiled before uploading to hosts." 21 | }, 22 | "destination": { 23 | "type": "string", 24 | "description": "The absolute path on the hosts where the compiled template needs to be uploaded" 25 | }, 26 | "apply_required": { 27 | "type": "boolean", 28 | "default": true, 29 | "description": "A switch to call the command to apply the uploaded template on remote hosts" 30 | }, 31 | "apply_command": { 32 | "type": "string", 33 | "description": "The command to apply the template on remote hosts after uploading it. It is called only if the switch apply_required is on." 34 | }, 35 | "sudo": { 36 | "type": "boolean", 37 | "default": true, 38 | "description": "A switch for the command execution from the sudoer" 39 | }, 40 | "destination_groups": { 41 | "$ref": "../../common/node_ref.json#/definitions/Roles", 42 | "description": "List of groups on which the compiled template needs to be uploaded" 43 | }, 44 | "destination_nodes": { 45 | "$ref": "../../common/node_ref.json#/definitions/Names", 46 | "description": "List of nodes on which the compiled template needs to be uploaded" 47 | }, 48 | "apply_groups": { 49 | "$ref": "../../common/node_ref.json#/definitions/Roles", 50 | "description": "List of groups on which the template apply command needs to be executed" 51 | }, 52 | "apply_nodes": { 53 | "$ref": "../../common/node_ref.json#/definitions/Names", 54 | "description": "List of nodes on which the template apply command needs to be executed" 55 | } 56 | } 57 | }, 58 | "PropertyNames": { 59 | "enum": [ 60 | "source", "destination", "apply_required", "apply_command", "sudo", 61 | "destination_groups", "destination_nodes", "apply_groups", "apply_nodes" 62 | ] 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/plugins/local-path-provisioner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Enable and/or change default settings for 'local-path-provisioner' plugin", 5 | "allOf": [{"$ref": "generic_plugin.json#/definitions/Properties"}], 6 | "properties": { 7 | "version": { 8 | "type": "string" 9 | }, 10 | "image": { 11 | "type": "string" 12 | }, 13 | "storage-class": { 14 | "type": "object", 15 | "description": "Configuration of StorageClass resource for Local Path Provisioner", 16 | "properties": { 17 | "name": { 18 | "type": "string", 19 | "default": "local-path", 20 | "description": "Name of the storage class resource, which describes the class of the local volumes created by the provisioner" 21 | }, 22 | "is-default": { 23 | "type": ["string", "boolean"], 24 | "default": "'false'", 25 | "description": "If 'true', the created storage class is the default one" 26 | } 27 | }, 28 | "additionalProperties": false 29 | }, 30 | "volume-dir": { 31 | "type": "string", 32 | "default": "/opt/local-path-provisioner", 33 | "description": "The directory on each node, where the provisioner stores the PV data. For each requested PV, the provisioner creates the subdirectory in the volume-dir." 34 | }, 35 | "tolerations": { 36 | "$ref": "generic_plugin.json#/definitions/CustomTolerations" 37 | }, 38 | "resources": { 39 | "$ref": "generic_plugin.json#/definitions/RequestsLimitsForContainer" 40 | }, 41 | "helper-pod-image": { 42 | "type": "string" 43 | } 44 | }, 45 | "propertyNames": { 46 | "anyOf": [ 47 | {"$ref": "generic_plugin.json#/definitions/PropertyNames"}, 48 | {"enum": ["version", "image", "storage-class", "volume-dir", "tolerations", "helper-pod-image", "resources"]} 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/procedures.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "definitions": { 4 | "PrepullGroupSize": { 5 | "type": "integer", 6 | "default": 20, 7 | "description": "Max number of nodes in groups, into which all nodes are split for simultaneous images prepull" 8 | }, 9 | "GracePeriod": { 10 | "type": "integer", 11 | "default": 60, 12 | "description": "Time to wait in seconds for the pods' migration to other nodes during draining before killing them" 13 | }, 14 | "DrainTimeout": { 15 | "type": "integer", 16 | "description": "Time to wait for the pods' killing" 17 | }, 18 | "DisableEviction": { 19 | "type": "boolean", 20 | "default": true, 21 | "description": "If specified to false, enforces PDB rules during the upgrade" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/rbac.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Section describing Kubernetes admission and accounts", 5 | "properties": { 6 | "account_defaults": { 7 | "$ref": "rbac/account_defaults.json" 8 | }, 9 | "accounts": { 10 | "type": "array", 11 | "description": "List of Kubernetes accounts", 12 | "items": { 13 | "$ref": "rbac/account.json" 14 | }, 15 | "minItems": 1 16 | }, 17 | "admission": { 18 | "enum": ["pss"], 19 | "default": "pss", 20 | "description": "Admission implementation switcher" 21 | }, 22 | "authenticated-issuer-discovery": { 23 | "type": "boolean", 24 | "default": false, 25 | "description": "Authenticated issuer discovery switcher" 26 | }, 27 | "pss": { 28 | "$ref": "rbac/pss.json" 29 | } 30 | }, 31 | "additionalProperties": false 32 | } 33 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/rbac/account.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "allOf": [{"$ref": "account_defaults.json#/definitions/CommonAccountProperties"}], 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Account name that is applied by default to items in 'configs' section" 9 | }, 10 | "role": { 11 | "type": "string", 12 | "description": "Account role that is applied to ClusterRoleBinding item in 'configs' section" 13 | } 14 | }, 15 | "required": ["name", "role"], 16 | "propertyNames": { 17 | "anyOf": [ 18 | {"$ref": "account_defaults.json#/definitions/CommonAccountPropertyNames"}, 19 | {"enum": ["name", "role"]} 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/rbac/pss.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "PSS configuration section", 5 | "allOf": [{"$ref": "#/definitions/Properties"}], 6 | "propertyNames": { 7 | "$ref": "#/definitions/PropertyNames" 8 | }, 9 | "definitions": { 10 | "Properties": { 11 | "properties": { 12 | "pod-security": { 13 | "enum": ["enabled", "disabled"], 14 | "default": "enabled", 15 | "description": "Specify if PSS should be enabled/disabled" 16 | }, 17 | "defaults": { 18 | "$ref": "#/definitions/Profiles", 19 | "description": "Default profiles that are passed to 'defaults' section of PodSecurityConfiguration" 20 | }, 21 | "exemptions": { 22 | "type": "object", 23 | "description": "The section describes objects that are not enforced by the policy", 24 | "properties": { 25 | "usernames": { 26 | "$ref": "../common/utils.json#/definitions/MergeableSetOfStrings", 27 | "description": "List of User or ServiceAccount names" 28 | }, 29 | "runtimeClasses": { 30 | "$ref": "../common/utils.json#/definitions/MergeableSetOfStrings" 31 | }, 32 | "namespaces": { 33 | "type": "array", 34 | "description": "List of namespaces to not enforce the policy", 35 | "items": { 36 | "anyOf": [ 37 | {"type": "string", "enum": ["kube-system"]}, 38 | {"type": "string"}, 39 | {"$ref": "../common/utils.json#/definitions/ListMergingSymbol"} 40 | ] 41 | }, 42 | "uniqueItems": true 43 | } 44 | }, 45 | "additionalProperties": false 46 | } 47 | } 48 | }, 49 | "PropertyNames": { 50 | "enum": ["pod-security", "defaults", "exemptions"] 51 | }, 52 | "Profiles": { 53 | "type": "object", 54 | "properties": { 55 | "enforce": {"$ref": "#/definitions/Profile"}, 56 | "enforce-version": {"$ref": "#/definitions/ProfileVersion"}, 57 | "audit": {"$ref": "#/definitions/Profile"}, 58 | "audit-version": {"$ref": "#/definitions/ProfileVersion"}, 59 | "warn": {"$ref": "#/definitions/Profile"}, 60 | "warn-version": {"$ref": "#/definitions/ProfileVersion"} 61 | }, 62 | "additionalProperties": false 63 | }, 64 | "Profile": { 65 | "enum": ["privileged", "baseline", "restricted"], 66 | "default": "baseline" 67 | }, 68 | "ProfileVersion": { 69 | "type": ["string"], 70 | "default": "latest" 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/registry.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Defines addresses of remote resources to use in private environments without access to internet", 5 | "oneOf": [ 6 | {"$ref": "#/definitions/NewEndpointsFormat"}, 7 | {"$ref": "#/definitions/OldAddressPortFormat"} 8 | ], 9 | "definitions": { 10 | "NewEndpointsFormat": { 11 | "type": "object", 12 | "properties": { 13 | "endpoints": { 14 | "$ref": "common/utils.json#/definitions/NonEmptySetOfStrings", 15 | "description": "Address list of registry endpoints" 16 | }, 17 | "mirror_registry": { 18 | "type": "string", 19 | "default": "registry.cluster.local", 20 | "description": "The internal address of the containerd mirror registry, which should be defined in containers" 21 | }, 22 | "thirdparties": { 23 | "type": "string", 24 | "description": "Address for the webserver, where thirdparties hosted" 25 | } 26 | }, 27 | "required": ["endpoints"], 28 | "additionalProperties": false 29 | }, 30 | "OldAddressPortFormat": { 31 | "type": "object", 32 | "properties": { 33 | "address": { 34 | "type": "string", 35 | "description": "Full address to the registry, without protocol and port" 36 | }, 37 | "docker_port": { 38 | "type": "integer", 39 | "minimum": 0, 40 | "maximum": 65535, 41 | "description": "Custom port for connecting to the image registry" 42 | }, 43 | "webserver": { 44 | "type": "boolean", 45 | "default": false, 46 | "description": "A special parameter indicating whether registry has ability to serve http files. When enabled, the 'thirdparties' are patched with the 'address' provided." 47 | }, 48 | "ssl": { 49 | "type": "boolean", 50 | "default": false, 51 | "description": "Registry SSL support switch" 52 | } 53 | }, 54 | "required": ["address"], 55 | "additionalProperties": false 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Configure settings of different services", 5 | "properties": { 6 | "kubeadm_kubelet": { 7 | "$ref": "services/kubeadm_kubelet.json" 8 | }, 9 | "kubeadm_kube-proxy": { 10 | "$ref": "services/kubeadm_kube-proxy.json" 11 | }, 12 | "kubeadm_patches": { 13 | "$ref": "services/kubeadm_patches.json" 14 | }, 15 | "kubeadm_flags": { 16 | "type": "object", 17 | "description": "Flags for kubeadm command line tool", 18 | "properties": { 19 | "ignorePreflightErrors": { 20 | "type": "string", 21 | "default": "Port-6443,CoreDNSUnsupportedPlugins", 22 | "description": "Kubeadm preflight errors to be ignored for a successful deploy or upgrade" 23 | } 24 | }, 25 | "additionalProperties": false 26 | }, 27 | "kubeadm": { 28 | "$ref": "services/kubeadm.json" 29 | }, 30 | "kernel_security": { 31 | "$ref": "services/kernel_security.json" 32 | }, 33 | "packages": { 34 | "$ref": "services/packages.json" 35 | }, 36 | "thirdparties": { 37 | "$ref": "services/thirdparties.json" 38 | }, 39 | "cri": { 40 | "$ref": "services/cri.json" 41 | }, 42 | "modprobe": { 43 | "$ref": "services/modprobe.json" 44 | }, 45 | "sysctl": { 46 | "$ref": "services/sysctl.json" 47 | }, 48 | "audit": { 49 | "$ref": "services/audit.json" 50 | }, 51 | "ntp": { 52 | "$ref": "services/ntp.json" 53 | }, 54 | "resolv.conf": { 55 | "$ref": "services/resolv.conf.json" 56 | }, 57 | "etc_hosts": { 58 | "$ref": "services/etc_hosts.json" 59 | }, 60 | "etc_hosts_generated": { 61 | "description": "Describes auto-generated records about nodes for /etc/hosts and coredns configmap. The key is an IP-address, the value is either a DNS name or an array of names.", 62 | "$ref": "services/etc_hosts.json" 63 | }, 64 | "coredns": { 65 | "$ref": "services/coredns.json" 66 | }, 67 | "loadbalancer": { 68 | "$ref": "services/loadbalancer.json" 69 | } 70 | }, 71 | "required": [], 72 | "additionalProperties": false 73 | } 74 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/audit.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Manage audit service and Kubernetes cluster policy", 5 | "properties": { 6 | "rules": { 7 | "$ref": "../common/utils.json#/definitions/MergeableSetOfStrings", 8 | "description": "Audit rules for auditd daemon to apply" 9 | }, 10 | "cluster_policy": { 11 | "type": "object", 12 | "description": "Policy for Kubernetes logging", 13 | "properties": { 14 | "apiVersion": {"type": ["string"], "default": "audit.k8s.io/v1"}, 15 | "kind": {"enum": ["Policy"], "default": "Policy"}, 16 | "omitStages": { 17 | "type": "array", 18 | "items": { 19 | "anyOf": [ 20 | { 21 | "type": "string", 22 | "enum": ["RequestReceived"] 23 | }, 24 | {"type": "string"}, 25 | {"$ref": "../common/utils.json#/definitions/ListMergingSymbol"} 26 | ] 27 | } 28 | }, 29 | "rules": { 30 | "type": "array", 31 | "items": { 32 | "oneOf": [ 33 | {"$ref": "#/definitions/PolicyRule"}, 34 | {"$ref": "../common/utils.json#/definitions/ListMergingSymbol"} 35 | ] 36 | } 37 | } 38 | } 39 | } 40 | }, 41 | "additionalProperties": false, 42 | "definitions": { 43 | "PolicyRule": { 44 | "type": "object", 45 | "properties": { 46 | "level": {"type": "string"}, 47 | "verbs": {"$ref": "../common/utils.json#/definitions/ArrayOfStrings"}, 48 | "resources": { 49 | "type": "array", 50 | "items": { 51 | "type": "object", 52 | "properties": { 53 | "group": {"type": "string"}, 54 | "resources": {"$ref": "../common/utils.json#/definitions/ArrayOfStrings"}, 55 | "resourceNames": {"$ref": "../common/utils.json#/definitions/ArrayOfStrings"} 56 | } 57 | } 58 | } 59 | }, 60 | "required": ["level"], 61 | "propertyNames": { 62 | "not": {"enum": ["<<"]} 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/cri.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Configure container runtime used for Kubernetes", 5 | "properties": { 6 | "containerRuntime": { 7 | "enum": ["containerd"], 8 | "default": "containerd", 9 | "description": "A particular container runtime implementation used for Kubernetes" 10 | }, 11 | "containerdConfig": { 12 | "$ref": "#/definitions/ContainerdConfig" 13 | }, 14 | "containerdRegistriesConfig": { 15 | "$ref": "#/definitions/ContainerdRegistriesConfig" 16 | } 17 | }, 18 | "additionalProperties": false, 19 | "definitions": { 20 | "ContainerdConfig": { 21 | "type": "object", 22 | "description": "Parameters for containerd passed to config.toml", 23 | "properties": { 24 | "version": {"type": "integer", "default": 2}, 25 | "plugins.\"io.containerd.grpc.v1.cri\"": { 26 | "type": "object", 27 | "properties": { 28 | "sandbox_image": {"type": "string"} 29 | } 30 | }, 31 | "plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc": { 32 | "type": "object", 33 | "properties": { 34 | "runtime_type": {"type": "string", "default": "io.containerd.runc.v2"} 35 | } 36 | }, 37 | "plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc.options": { 38 | "type": "object", 39 | "properties": { 40 | "SystemdCgroup": {"type": ["string", "boolean"]} 41 | } 42 | } 43 | } 44 | }, 45 | "ContainerdRegistriesConfig": { 46 | "type": "object", 47 | "description": "Parameters for containerd passed to /etc/containerd/certs.d or another place, configured in config_path in config.toml", 48 | "additionalProperties": { 49 | "type": "object", 50 | "description": "Parameters for containerd passed to hosts.toml for specific registry" 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/etc_hosts.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Specify custom records for /etc/hosts. The key is an IP-address, the value is either a DNS name or an array of names.", 5 | "properties": { 6 | "127.0.0.1": { 7 | "$ref": "#/definitions/DNSNames" 8 | }, 9 | "::1": { 10 | "$ref": "#/definitions/DNSNames" 11 | } 12 | }, 13 | "additionalProperties": { 14 | "$ref": "#/definitions/DNSNames" 15 | }, 16 | "definitions": { 17 | "DNSNames": { 18 | "description": "IP-address", 19 | "oneOf": [ 20 | {"type": "string"}, 21 | {"$ref": "../common/utils.json#/definitions/MergeableSetOfStrings"} 22 | ] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/kernel_security.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Common section for selinux and apparmor properties", 5 | "properties": { 6 | "apparmor": { 7 | "$ref": "#/definitions/AppArmor" 8 | }, 9 | "selinux": { 10 | "$ref": "#/definitions/SELinux" 11 | } 12 | }, 13 | "additionalProperties": false, 14 | "definitions": { 15 | "AppArmor": { 16 | "type": "object", 17 | "description": "Declare the already existing AppArmor profiles, the state of which needs to be changed", 18 | "properties": { 19 | "enforce": { 20 | "$ref": "../common/utils.json#/definitions/ArrayOfStrings", 21 | "description": "Default mode, prohibits everything according to the profile settings" 22 | }, 23 | "complain": { 24 | "$ref": "../common/utils.json#/definitions/ArrayOfStrings", 25 | "description": "Does not prohibit, but only displays violation warnings in the logs" 26 | }, 27 | "disable": { 28 | "$ref": "../common/utils.json#/definitions/ArrayOfStrings", 29 | "description": "Disables and unloads security profile" 30 | } 31 | }, 32 | "additionalProperties": false 33 | }, 34 | "SELinux": { 35 | "type": "object", 36 | "description": "SELinux settings", 37 | "properties": { 38 | "state": { 39 | "enum": ["enforcing", "permissive", "disabled"], 40 | "default": "enforcing", 41 | "description": "Defines the top-level state of SELinux on a system" 42 | }, 43 | "policy": { 44 | "enum": ["targeted", "strict"], 45 | "default": "targeted", 46 | "description": "Specifies which policy is currently being enforced by SELinux." 47 | }, 48 | "permissive": { 49 | "$ref": "../common/utils.json#/definitions/MergeableSetOfStrings", 50 | "description": "Certain SELinux object type policy records, applicable without requiring modification to or recompilation from the policy sources" 51 | } 52 | }, 53 | "additionalProperties": false 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/kubeadm_kube-proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Override the original settings for the kube-proxy", 5 | "allOf": [{"$ref": "#/definitions/PayloadProperties"}], 6 | "properties": { 7 | "apiVersion": {"enum": ["kubeproxy.config.k8s.io/v1alpha1"], "default": "kubeproxy.config.k8s.io/v1alpha1"}, 8 | "kind": {"enum": ["KubeProxyConfiguration"], "default": "KubeProxyConfiguration"} 9 | }, 10 | "definitions": { 11 | "PayloadProperties": { 12 | "type": "object", 13 | "properties": { 14 | "conntrack": { 15 | "type": "object", 16 | "description": "Conntrack settings for the Kubernetes proxy server", 17 | "properties": { 18 | "min": { 19 | "type": ["string", "integer"], 20 | "description": "Minimum value of connect-tracking records to allocate. By default, inherits the `services.sysctl.net.netfilter.nf_conntrack_max` value.", 21 | "default": 1000000 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/kubeadm_kubelet.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Override the original settings for the kubelet", 5 | "properties": { 6 | "readOnlyPort": {"type": "integer", "default": 0}, 7 | "enableDebuggingHandlers": {"type": "boolean", "default": true}, 8 | "protectKernelDefaults": {"$ref": "#/definitions/ProtectKernelDefaults"}, 9 | "podPidsLimit": {"$ref": "#/definitions/PodPidsLimit"}, 10 | "cgroupDriver": {"type": "string", "default": "systemd"}, 11 | "maxPods": {"$ref": "#/definitions/MaxPods"}, 12 | "serializeImagePulls": {"$ref": "#/definitions/SerializeImagePulls"}, 13 | "apiVersion": {"type": ["string"], "default": "kubelet.config.k8s.io/v1beta1"}, 14 | "kind": {"enum": ["KubeletConfiguration"], "default": "KubeletConfiguration"} 15 | }, 16 | "definitions": { 17 | "ProtectKernelDefaults": {"type": "boolean", "default": true}, 18 | "PodPidsLimit": {"type": "integer", "default": 4096}, 19 | "MaxPods": {"type": "integer", "default": 110}, 20 | "SerializeImagePulls": {"type": "boolean", "default": false} 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/modprobe.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "debian": {"$ref": "#/definitions/OSFamilyModules"}, 6 | "rhel": {"$ref": "#/definitions/OSFamilyModules"}, 7 | "rhel8": {"$ref": "#/definitions/OSFamilyModules"}, 8 | "rhel9": {"$ref": "#/definitions/OSFamilyModules"} 9 | }, 10 | "propertyNames": { 11 | "anyOf": [ 12 | {"enum": ["debian", "rhel", "rhel8", "rhel9"]} 13 | ] 14 | }, 15 | "definitions": { 16 | "OSFamilyModules": { 17 | "type": "array", 18 | "description": "Manage Linux Kernel modules to be loaded in the host operating system. Each item can be either a module name, or dictionary with the module name and additional parameters.", 19 | "items": { 20 | "anyOf": [ 21 | { 22 | "type": "string", 23 | "enum": ["br_netfilter", "ip6table_filter", "nf_conntrack_ipv6", "nf_nat_masquerade_ipv6", "nf_reject_ipv6", "nf_defrag_ipv6", "nf_nat", "nf_conntrack"] 24 | }, 25 | {"type": "string"}, 26 | { 27 | "oneOf": [ 28 | {"$ref": "#/definitions/FilteredModule"}, 29 | {"$ref": "../common/utils.json#/definitions/ListMergingSymbol"} 30 | ] 31 | } 32 | ] 33 | }, 34 | "uniqueItems": true 35 | }, 36 | "FilteredModule": { 37 | "type": "object", 38 | "properties": { 39 | "modulename": { 40 | "type": "string", 41 | "description": "Module name in extended format" 42 | }, 43 | "groups": { 44 | "$ref": "../common/node_ref.json#/definitions/Roles", 45 | "default": ["worker", "control-plane", "balancer"], 46 | "description": "The list of group names in whose hosts the module should be loaded" 47 | }, 48 | "nodes": { 49 | "$ref": "../common/node_ref.json#/definitions/Names", 50 | "description": "The list of node names where the module should be loaded" 51 | }, 52 | "install": { 53 | "type": ["string", "boolean"], 54 | "default": "true", 55 | "description": "Whether the module is managed (installed, checked) by Kubemarine" 56 | } 57 | }, 58 | "required": ["modulename"], 59 | "additionalProperties": false 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/ntp.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "This is a common section for chrony and timesyncd properties", 5 | "properties": { 6 | "chrony": { 7 | "$ref": "#/definitions/Chrony" 8 | }, 9 | "timesyncd": { 10 | "$ref": "#/definitions/Timesyncd" 11 | } 12 | }, 13 | "additionalProperties": false, 14 | "definitions": { 15 | "Chrony": { 16 | "type": "object", 17 | "description": "Section for chrony properties", 18 | "properties": { 19 | "servers": { 20 | "$ref": "../common/utils.json#/definitions/NonEmptySetOfStrings", 21 | "description": "NTP servers addresses with additional configurations" 22 | }, 23 | "makestep": { 24 | "type": "string", 25 | "default": "5 -1", 26 | "description": "Step the system clock if large correction is needed" 27 | }, 28 | "rtcsync": { 29 | "type": "boolean", 30 | "default": true, 31 | "description": "Specify that RTC should be automatically synchronized by kernel" 32 | } 33 | }, 34 | "additionalProperties": false 35 | }, 36 | "Timesyncd": { 37 | "type": "object", 38 | "description": "Section for timesyncd properties", 39 | "properties": { 40 | "Time": { 41 | "type": "object", 42 | "description": "Specify NTP servers and/or override default parameters", 43 | "properties": { 44 | "NTP": { 45 | "$ref": "../common/utils.json#/definitions/NonEmptySetOfStrings", 46 | "description": "NTP servers addresses" 47 | }, 48 | "FallbackNTP": { 49 | "$ref": "../common/utils.json#/definitions/NonEmptySetOfStrings", 50 | "description": "Backup NTP servers addresses when NTP servers are unavailable" 51 | }, 52 | "RootDistanceMaxSec": { 53 | "type": "integer", 54 | "default": 5, 55 | "description": "Step the system clock if large correction is needed" 56 | }, 57 | "PollIntervalMinSec": { 58 | "type": "integer", 59 | "default": 32, 60 | "description": "The minimal poll interval" 61 | }, 62 | "PollIntervalMaxSec": { 63 | "type": "integer", 64 | "default": 2048, 65 | "description": "The maximum poll interval" 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/resolv.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Configure the nameserver addresses to which cluster systems has access", 5 | "properties": { 6 | "search": { 7 | "type": "string", 8 | "description": "The domain name to search" 9 | }, 10 | "nameservers": { 11 | "$ref": "../common/utils.json#/definitions/NonEmptySetOfStrings", 12 | "description": "The DNS servers for usage in the OS" 13 | } 14 | }, 15 | "additionalProperties": false 16 | } 17 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/definitions/services/sysctl.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "description": "Manage the Linux Kernel parameters for all hosts in a cluster", 5 | "properties": { 6 | "net.bridge.bridge-nf-call-iptables": { 7 | "$ref": "#/definitions/GenericValue", 8 | "default": 1 9 | }, 10 | "net.ipv4.ip_forward": { 11 | "$ref": "#/definitions/GenericValue", 12 | "default": 1 13 | }, 14 | "net.ipv4.ip_nonlocal_bind": { 15 | "$ref": "#/definitions/GenericValue", 16 | "default": 1 17 | }, 18 | "net.ipv4.conf.all.route_localnet": { 19 | "$ref": "#/definitions/GenericValue", 20 | "default": 1 21 | }, 22 | "net.bridge.bridge-nf-call-ip6tables": { 23 | "$ref": "#/definitions/GenericValue" 24 | }, 25 | "net.ipv6.conf.all.forwarding": { 26 | "$ref": "#/definitions/GenericValue" 27 | }, 28 | "net.ipv6.ip_nonlocal_bind": { 29 | "$ref": "#/definitions/GenericValue" 30 | }, 31 | "net.netfilter.nf_conntrack_max": { 32 | "$ref": "#/definitions/GenericValue", 33 | "default": 1000000 34 | }, 35 | "kernel.panic": { 36 | "$ref": "#/definitions/GenericValue", 37 | "default": 10 38 | }, 39 | "vm.overcommit_memory": { 40 | "$ref": "#/definitions/GenericValue", 41 | "default": 1 42 | }, 43 | "kernel.panic_on_oops": { 44 | "$ref": "#/definitions/GenericValue", 45 | "default": 1 46 | }, 47 | "kernel.pid_max": { 48 | "$ref": "#/definitions/GenericValue", 49 | "description": "If this parameter is not explicitly indicated in the cluster.yaml, then this value is calculated by this formula: maxPods * podPidsLimit + 2048" 50 | } 51 | }, 52 | "additionalProperties": { 53 | "$ref": "#/definitions/GenericValue" 54 | }, 55 | "definitions": { 56 | "SimpleValue": { 57 | "type": ["string", "integer"], 58 | "description": "The value can be an integer value, or template string to be rendered as an integer value" 59 | }, 60 | "FilteredValue": { 61 | "type": "object", 62 | "properties": { 63 | "value": { 64 | "$ref": "#/definitions/SimpleValue" 65 | }, 66 | "groups": { 67 | "$ref": "../common/node_ref.json#/definitions/Roles", 68 | "default": ["worker", "control-plane", "balancer"], 69 | "description": "The list of group names to whose hosts the parameter should be set" 70 | }, 71 | "nodes": { 72 | "$ref": "../common/node_ref.json#/definitions/Names", 73 | "description": "The list of node names where the parameter should be set" 74 | }, 75 | "install": { 76 | "type": ["string", "boolean"], 77 | "default": "true", 78 | "description": "Whether the parameter is managed (installed, checked) by Kubemarine" 79 | } 80 | }, 81 | "required": ["value"], 82 | "additionalProperties": false 83 | }, 84 | "GenericValue": { 85 | "oneOf": [ 86 | {"$ref": "#/definitions/SimpleValue"}, 87 | {"$ref": "#/definitions/FilteredValue"} 88 | ], 89 | "description": "The value can be an integer value, template string to be rendered as an integer value, or dictionary with the value and additional parameters." 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/internal/connections.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "nodes": { 6 | "type": "array", 7 | "description": "Describe each node of the cluster.", 8 | "minItems": 1, 9 | "items": { 10 | "type": "object", 11 | "allOf": [{"$ref": "../definitions/node.json#/definitions/AccessProperties"}], 12 | "properties": { 13 | "roles": { 14 | "$ref": "#/definitions/LegacyRoles", 15 | "description": "Cluster member roles" 16 | } 17 | }, 18 | "required": ["internal_address", "roles"] 19 | } 20 | }, 21 | "node_defaults": { 22 | "type": "object", 23 | "description": "Section to hold the parameters to be applied by default to each record in the nodes section", 24 | "allOf": [{"$ref": "../definitions/node_defaults.json#/definitions/CommonNodeAccessProperties"}] 25 | }, 26 | "gateway_nodes": { 27 | "$ref": "../cluster.json#/definitions/GatewayNodes" 28 | }, 29 | "procedure_history": { 30 | "$ref": "../cluster.json#/definitions/ProcedureHistory" 31 | } 32 | }, 33 | "required": ["nodes"], 34 | "definitions": { 35 | "LegacyRole": { 36 | "enum": ["worker", "control-plane", "master", "balancer"] 37 | }, 38 | "LegacyRoles": { 39 | "type": "array", 40 | "items": { 41 | "$ref": "#/definitions/LegacyRole" 42 | }, 43 | "uniqueItems": true, 44 | "minItems": 1 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/manage_pss.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "pss": { 6 | "type": "object", 7 | "description": "PSS configuration section", 8 | "allOf": [{"$ref": "definitions/rbac/pss.json#/definitions/Properties"}], 9 | "properties": { 10 | "namespaces": { 11 | "type": "array", 12 | "description": "List of namespaces that will be labeled during the maintenance procedure. Each item can be either a namespace name, or dictionary where key is a namespace name and values are profile labels.", 13 | "items": { 14 | "oneOf": [ 15 | {"type": "string"}, 16 | { 17 | "type": "object", 18 | "additionalProperties": { 19 | "$ref": "definitions/rbac/pss.json#/definitions/Profiles" 20 | }, 21 | "minProperties": 1, 22 | "maxProperties": 1 23 | } 24 | ] 25 | } 26 | }, 27 | "namespaces_defaults": { 28 | "$ref": "definitions/rbac/pss.json#/definitions/Profiles", 29 | "description": "Labels to be applied on namespaces list from 'namespaces' section" 30 | } 31 | }, 32 | "required": ["pod-security"], 33 | "propertyNames": { 34 | "anyOf": [ 35 | {"$ref": "definitions/rbac/pss.json#/definitions/PropertyNames"}, 36 | {"enum": ["namespaces", "namespaces_defaults"]} 37 | ] 38 | } 39 | }, 40 | "restart-pods": { 41 | "type": "boolean", 42 | "default": false, 43 | "description": "Enforce restart all pods in cluster. It drains nodes one by one and may cause cluster instability." 44 | } 45 | }, 46 | "required": ["pss"], 47 | "additionalProperties": false 48 | } 49 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/migrate_kubemarine.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "upgrade": { 6 | "type": "object", 7 | "description": "Configure the parameters to upgrade different types of software", 8 | "properties": { 9 | "plugins": { 10 | "$ref": "#/definitions/UpgradePlugins" 11 | }, 12 | "packages": { 13 | "$ref": "#/definitions/UpgradePackages" 14 | }, 15 | "thirdparties": { 16 | "$ref": "#/definitions/UpgradeThirdparties" 17 | } 18 | }, 19 | "additionalProperties": false 20 | }, 21 | "disable-eviction": {"$ref": "definitions/procedures.json#/definitions/DisableEviction"}, 22 | "grace_period": {"$ref": "definitions/procedures.json#/definitions/GracePeriod"}, 23 | "drain_timeout": {"$ref": "definitions/procedures.json#/definitions/DrainTimeout"} 24 | }, 25 | "additionalProperties": false, 26 | "definitions": { 27 | "UpgradePlugins": { 28 | "type": "object", 29 | "description": "Configure the parameters of the default plugins", 30 | "properties": { 31 | "calico": { 32 | "$ref": "definitions/plugins/calico.json" 33 | }, 34 | "nginx-ingress-controller": { 35 | "$ref": "definitions/plugins/nginx-ingress-controller.json" 36 | }, 37 | "kubernetes-dashboard": { 38 | "$ref": "definitions/plugins/kubernetes-dashboard.json" 39 | }, 40 | "local-path-provisioner": { 41 | "$ref": "definitions/plugins/local-path-provisioner.json" 42 | } 43 | }, 44 | "additionalProperties": false 45 | }, 46 | "UpgradePackages": { 47 | "type": "object", 48 | "description": "Section for packages and their management during upgrade", 49 | "properties": { 50 | "associations": { 51 | "type": "object", 52 | "description": "Configure associations of package objects to be used during upgrade", 53 | "properties": { 54 | "containerd": {"$ref": "definitions/services/packages/associations.json#/definitions/PackageNameOnlyAssociations"}, 55 | "haproxy": {"$ref": "definitions/services/packages/associations.json#/definitions/PackageNameOnlyAssociations"}, 56 | "keepalived": {"$ref": "definitions/services/packages/associations.json#/definitions/PackageNameOnlyAssociations"} 57 | }, 58 | "additionalProperties": false 59 | } 60 | }, 61 | "additionalProperties": false 62 | }, 63 | "UpgradeThirdparties": { 64 | "type": "object", 65 | "description": "Deliver files from third party sources and install them in the system", 66 | "properties": { 67 | "/usr/bin/calicoctl": {"$ref": "definitions/services/thirdparties.json#/definitions/ThirdParty"}, 68 | "/usr/bin/crictl.tar.gz": {"$ref": "definitions/services/thirdparties.json#/definitions/ThirdParty"} 69 | }, 70 | "additionalProperties": false 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/reboot.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "graceful_reboot": { 6 | "type": "boolean", 7 | "default": false, 8 | "description": "What type of reboot to perform. If specified to true, pods are drained to other nodes and the nodes are rebooted one after another." 9 | }, 10 | "nodes": { 11 | "type": "array", 12 | "description": "List of node names that should be rebooted. By default, all nodes are rebooted.", 13 | "items": { 14 | "type": "object", 15 | "properties": { 16 | "name": { 17 | "$ref": "definitions/common/node_ref.json#/definitions/Name" 18 | } 19 | }, 20 | "required": ["name"], 21 | "additionalProperties": false 22 | }, 23 | "minItems": 1 24 | } 25 | }, 26 | "additionalProperties": false 27 | } 28 | -------------------------------------------------------------------------------- /kubemarine/resources/schemas/remove_node.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "nodes": { 6 | "type": "array", 7 | "description": "Nodes to remove. Each item can be specified in the same format as that of the installation procedure, or in short format where only the node name is present.", 8 | "items": { 9 | "type": "object", 10 | "allOf": [{"$ref": "definitions/node.json#/definitions/Properties"}], 11 | "required": ["name"], 12 | "propertyNames": { 13 | "$ref": "definitions/node.json#/definitions/PropertyNames" 14 | } 15 | }, 16 | "minItems": 1, 17 | "uniqueItems": true 18 | }, 19 | "grace_period": {"$ref": "definitions/procedures.json#/definitions/GracePeriod"}, 20 | "drain_timeout": {"$ref": "definitions/procedures.json#/definitions/DrainTimeout"} 21 | }, 22 | "required": ["nodes"], 23 | "additionalProperties": false 24 | } 25 | -------------------------------------------------------------------------------- /kubemarine/resources/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/resources/scripts/check_haproxy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script simply checks that ports 80, 443 and 6443 are listened by haproxy process 4 | 5 | HAPROXY_PROC_NAME='haproxy' 6 | 7 | for port in 80 443 6443; do 8 | if ! ss -ntpl sport = :${port} | grep ${HAPROXY_PROC_NAME}; then 9 | echo "Haproxy do not listen on port $port" 10 | exit 1 11 | fi 12 | done -------------------------------------------------------------------------------- /kubemarine/resources/scripts/check_url_availability.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Check url availability script. 16 | # The script is for testing purpose only. 17 | # The first argv parameter is source. The second argv parameter is the timeout. 18 | 19 | import ssl 20 | import sys 21 | 22 | major_version = sys.version_info.major 23 | if major_version == 3: 24 | import urllib.request as urllib 25 | import urllib.parse as urlparse 26 | else: 27 | # pylint: disable-next=import-error 28 | import urllib2 as urllib # type: ignore[import-not-found, no-redef] 29 | # pylint: disable-next=import-error 30 | import urlparse # type: ignore[import-not-found, no-redef] 31 | 32 | try: 33 | source = sys.argv[1] 34 | timeout = int(sys.argv[2]) 35 | parsed_url = urlparse.urlparse(source) 36 | no_auth_netloc = parsed_url.netloc.split('@')[-1] 37 | no_auth_url = parsed_url._replace(netloc="{}".format(no_auth_netloc)).geturl() 38 | 39 | password_mgr = urllib.HTTPPasswordMgrWithDefaultRealm() 40 | password_mgr.add_password(None, no_auth_url, parsed_url.username or '', parsed_url.password or '') 41 | basic_auth_handler = urllib.HTTPBasicAuthHandler(password_mgr) 42 | 43 | ssl_ctx = ssl.create_default_context() 44 | ssl_ctx.check_hostname = False 45 | ssl_ctx.verify_mode = ssl.CERT_NONE 46 | https_handler = urllib.HTTPSHandler(context=ssl_ctx) 47 | 48 | opener = urllib.build_opener(https_handler, basic_auth_handler) 49 | 50 | status_code = opener.open(no_auth_url, timeout=timeout).getcode() 51 | if status_code != 200: 52 | sys.stderr.write("Error status code: %s" % status_code) 53 | sys.exit(1) 54 | except Exception as e: 55 | sys.stderr.write(str(e)) 56 | sys.exit(1) 57 | -------------------------------------------------------------------------------- /kubemarine/resources/scripts/simple_port_client.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import socket 17 | import sys 18 | 19 | action = sys.argv[1] 20 | port = int(sys.argv[2]) 21 | address = sys.argv[3] 22 | ip_version = sys.argv[4] 23 | 24 | proto = '{{ proto }}' 25 | 26 | s_type = socket.SOCK_STREAM 27 | if proto == 'udp': 28 | s_type = socket.SOCK_DGRAM 29 | 30 | family = socket.AF_INET 31 | if ip_version == '6': 32 | family = socket.AF_INET6 33 | 34 | s = socket.socket(family, s_type) 35 | try: 36 | s.settimeout(int('{{ timeout }}')) 37 | 38 | sz = int('{{ mtu }}') 39 | 40 | if proto == 'udp': 41 | s.sendto(os.urandom(sz), (address, port)) 42 | data, server = s.recvfrom(sz) 43 | else: 44 | s.connect((address, port)) 45 | data = bytearray() 46 | if action == 'send': 47 | s.sendall(os.urandom(sz)) 48 | while len(data) < sz: 49 | data.extend(s.recv(sz)) 50 | finally: 51 | s.close() 52 | 53 | if action == 'send' and len(data) != sz: 54 | sys.stdout.write("Data is lost\n") 55 | sys.stdout.flush() 56 | sys.exit(1) 57 | -------------------------------------------------------------------------------- /kubemarine/resources/scripts/simple_port_listener.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Simple TCP socket listener that can be run on both python 2 and 3, 16 | # The listener accepts connections sequentially, and suppresses the received data. 17 | # The script is for testing purpose only. 18 | # The first argv parameter is the TCP port to listen. The second argv parameter is the ip protocol version. 19 | 20 | import socket 21 | import sys 22 | 23 | port = int(sys.argv[1]) 24 | 25 | proto = '{{ proto }}' 26 | ip_version = '{{ ip_version }}' 27 | 28 | s_type = socket.SOCK_STREAM 29 | if proto == 'udp': 30 | s_type = socket.SOCK_DGRAM 31 | 32 | family = socket.AF_INET 33 | if ip_version == '6': 34 | family = socket.AF_INET6 35 | 36 | s = socket.socket(family, s_type) 37 | try: 38 | try: 39 | s.bind(('{{ address }}', port)) 40 | except socket.error as e: 41 | if "Address already in use" in str(e): 42 | sys.stdout.write("In use\n") 43 | sys.stdout.flush() 44 | sys.exit(1) 45 | else: 46 | raise 47 | 48 | sys.stdout.write("Listen\n") 49 | sys.stdout.flush() 50 | 51 | sz = int('{{ mtu }}') 52 | 53 | if proto == 'udp': 54 | while True: 55 | data, address = s.recvfrom(sz) 56 | s.sendto(data, address) 57 | 58 | else: 59 | s.listen(1) 60 | 61 | while True: 62 | client, _ = s.accept() 63 | try: 64 | while True: 65 | data = client.recv(sz) 66 | if not data: 67 | break 68 | client.sendall(data) 69 | finally: 70 | client.close() 71 | finally: 72 | s.close() 73 | -------------------------------------------------------------------------------- /kubemarine/resources/scripts/source/ipip_check/go.mod: -------------------------------------------------------------------------------- 1 | module ipip_check 2 | 3 | go 1.24.1 4 | 5 | require github.com/google/gopacket v1.1.19 6 | -------------------------------------------------------------------------------- /kubemarine/resources/scripts/source/ipip_check/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 2 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 3 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 4 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 5 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 6 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 7 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 8 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 9 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 10 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 11 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 12 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 13 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 14 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 15 | -------------------------------------------------------------------------------- /kubemarine/templates/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/templates/admission.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: apiserver.config.k8s.io/v1 2 | kind: AdmissionConfiguration 3 | plugins: 4 | - name: PodSecurity 5 | configuration: 6 | apiVersion: pod-security.admission.config.k8s.io/v1beta1 7 | kind: PodSecurityConfiguration 8 | defaults: 9 | enforce: {{ defaults["enforce"] }} 10 | enforce-version: {{ defaults["enforce-version"] }} 11 | audit: {{ defaults["audit"] }} 12 | audit-version: {{ defaults["audit-version"] }} 13 | warn: {{ defaults["warn"] }} 14 | warn-version: {{ defaults["warn-version"] }} 15 | exemptions: 16 | usernames: {{ exemptions["usernames"] }} 17 | runtimeClasses: {{ exemptions["runtimeClasses"] }} 18 | namespaces: {{ exemptions["namespaces"] }} 19 | -------------------------------------------------------------------------------- /kubemarine/templates/haproxy.cfg.j2: -------------------------------------------------------------------------------- 1 | global 2 | log 127.0.0.1 local2 debug 3 | user haproxy 4 | group haproxy 5 | maxconn {{ config_options['global']['maxconn'] }} 6 | 7 | defaults 8 | log global 9 | option dontlognull 10 | timeout connect {{ config_options['defaults']['timeout_connect'] }} 11 | timeout client {{ config_options['defaults']['timeout_client'] }} 12 | timeout server {{ config_options['defaults']['timeout_server'] }} 13 | timeout tunnel {{ config_options['defaults']['timeout_tunnel'] }} 14 | timeout client-fin {{ config_options['defaults']['timeout_client_fin'] }} 15 | maxconn {{ config_options['defaults']['maxconn'] }} 16 | 17 | frontend http 18 | {%- for binding in bindings %} 19 | bind {{ binding }}:80 20 | {%- endfor %} 21 | option tcplog 22 | mode tcp 23 | default_backend http_backend 24 | 25 | backend http_backend 26 | mode tcp 27 | balance source 28 | option tcp-check 29 | default-server inter 2s fall 2 rise 3 30 | {%- for node in nodes -%} 31 | {% if 'worker' in node['roles'] %} 32 | server {{ node['name'] }} {{ node['internal_address'] }}:{{ target_ports.http }} check port {{ target_ports.http }} send-proxy 33 | {%- endif %} 34 | {%- endfor %} 35 | 36 | frontend https 37 | {%- for binding in bindings %} 38 | bind {{ binding }}:443 39 | {%- endfor %} 40 | option tcplog 41 | mode tcp 42 | default_backend https_backend 43 | 44 | backend https_backend 45 | mode tcp 46 | balance source 47 | option tcp-check 48 | default-server inter 2s fall 2 rise 3 49 | {%- for node in nodes -%} 50 | {% if 'worker' in node['roles'] %} 51 | server {{ node['name'] }} {{ node['internal_address'] }}:{{ target_ports.https }} check port {{ target_ports.https }} send-proxy 52 | {%- endif %} 53 | {%- endfor %} 54 | 55 | frontend kubernetes_api 56 | {%- for binding in bindings %} 57 | bind {{ binding }}:6443 58 | {%- endfor %} 59 | option tcplog 60 | mode tcp 61 | default_backend kubernetes_control_plane_nodes 62 | 63 | backend kubernetes_control_plane_nodes 64 | mode tcp 65 | balance roundrobin 66 | option tcp-check 67 | default-server inter 2s fall 2 rise 3 68 | {%- for node in nodes -%} 69 | {% if 'control-plane' in node['roles'] %} 70 | server {{ node['name'] }} {{ node['internal_address'] }}:6443 check port 6443 71 | {%- endif %} 72 | {%- endfor %} 73 | 74 | -------------------------------------------------------------------------------- /kubemarine/templates/keepalived.conf.j2: -------------------------------------------------------------------------------- 1 | {% if globals|length %} 2 | global_defs { 3 | {% if globals['vrrp_garp_master_refresh'] is defined %}vrrp_garp_master_refresh {{ globals['vrrp_garp_master_refresh'] }}{% endif %} 4 | } 5 | {% endif %} 6 | 7 | {%- for item in vrrp_ips %} 8 | vrrp_script script_{{ item['id'] }} { 9 | script "/usr/local/bin/check_haproxy.sh" 10 | interval 2 11 | fall 2 12 | rise 2 13 | } 14 | 15 | 16 | vrrp_instance balancer_{{ item['id'] }} { 17 | state BACKUP 18 | interface {{ item['interface'] }} 19 | virtual_router_id {{ item['router_id'] }} 20 | priority {{ item['priority'] }} 21 | nopreempt 22 | virtual_ipaddress { 23 | {{ item['ip'] }} dev {{ item['interface'] }} label vip_{{ item['id'] }} 24 | } 25 | 26 | track_script { 27 | script_{{ item['id'] }} 28 | } 29 | 30 | authentication { 31 | auth_type PASS 32 | auth_pass {{ item['password'] }} 33 | } 34 | 35 | {%- if item['peers'] | length > 0 %} 36 | unicast_src_ip {{ item['source'] }} 37 | unicast_peer { 38 | {%- for ip in item['peers'] %} 39 | {{ ip }} 40 | {%- endfor %} 41 | } 42 | {%- endif %} 43 | } 44 | 45 | {%- endfor %} 46 | -------------------------------------------------------------------------------- /kubemarine/templates/kubelet.service.j2: -------------------------------------------------------------------------------- 1 | # Note: This dropin only works with kubeadm and kubelet v1.11+ 2 | [Service] 3 | Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" 4 | Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" 5 | # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically 6 | EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env 7 | # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use 8 | # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. 9 | EnvironmentFile=-/etc/sysconfig/kubelet 10 | ExecStart= 11 | ExecStart=/usr/bin/kubelet --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice --hostname-override={{ hostname }} $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS 12 | Restart=on-failure 13 | RestartSec=5 14 | CPUAccounting=true 15 | MemoryAccounting=true 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /kubemarine/templates/patches/control-plane-pod.json.j2: -------------------------------------------------------------------------------- 1 | [ 2 | {%- for key, value in flags.items() -%} 3 | { "op": "add", "path": "/spec/containers/0/command/-", "value": "--{{ key }}={{ value }}" }, 4 | {%- endfor %} 5 | ] 6 | -------------------------------------------------------------------------------- /kubemarine/templates/patches/kubelet.yaml.j2: -------------------------------------------------------------------------------- 1 | {%- for key, value in flags.items() %} 2 | {{ key }}: {{ value }} 3 | {%- endfor %} 4 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calico-ippool.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: projectcalico.org/v3 2 | kind: IPPool 3 | metadata: 4 | name: {% if services.kubeadm.networking.podSubnet|isipv4 %}default-ipv4-ippool{% else %}default-ipv6-ippool{% endif %} 5 | spec: 6 | cidr: {% if services.kubeadm.networking.podSubnet|isipv4 %}{{ plugins['calico']['cni']['ipam']['ipv4']['ipv4_pools'][0] }}{% else %}{{ plugins['calico']['cni']['ipam']['ipv6']['ipv6_pools'][0] }}{% endif %} 7 | natOutgoing: {{ plugins['calico']['natOutgoing'] }} 8 | nodeSelector: all() 9 | {% if services.kubeadm.networking.podSubnet|isipv4 %} 10 | vxlanMode: {% if plugins.calico.mode == 'vxlan' and plugins['calico']['crossSubnet'] %}CrossSubnet{% elif plugins.calico.mode == 'vxlan' %}Always{% else %}Never{% endif %} 11 | ipipMode: {% if plugins.calico.mode == 'ipip' and plugins['calico']['crossSubnet'] %}CrossSubnet{% elif plugins.calico.mode == 'ipip' %}Always{% else %}Never{% endif %} 12 | {% endif %} 13 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calico-kube-controllers-metrics.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: calico-kube-controllers-metrics 5 | namespace: kube-system 6 | labels: 7 | k8s-app: calico-kube-controllers 8 | spec: 9 | clusterIP: None 10 | selector: 11 | k8s-app: calico-kube-controllers 12 | ports: 13 | - name: metrics 14 | port: 9094 15 | targetPort: 9094 -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calico-metrics.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: calico-metrics 5 | namespace: kube-system 6 | labels: 7 | k8s-app: calico-node 8 | spec: 9 | clusterIP: None 10 | selector: 11 | k8s-app: calico-node 12 | ports: 13 | - name: metrics 14 | port: 9091 15 | targetPort: 9091 -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calico-rr.sh.j2: -------------------------------------------------------------------------------- 1 | {% if not plugins.calico.fullmesh %} 2 | kubectl get nodes -l route-reflector=True 2>/dev/null | awk '{print $1}' | grep -vw NAME | xargs -I NODENAME calicoctl patch node NODENAME -p '{"spec": {"bgp": {"routeReflectorClusterID": "244.0.0.1"}}}' 3 | {% else %} 4 | kubectl get nodes 2>/dev/null | awk '{print $1}' | grep -vw NAME | xargs -I NODENAME calicoctl patch node NODENAME -p '{"spec": {"bgp": {"routeReflectorClusterID": ""}}}' 5 | {% endif %} 6 | 7 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calico-rr.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # This is default bgp configuration for calico bird 4 | 5 | apiVersion: crd.projectcalico.org/v1 6 | kind: BGPConfiguration 7 | metadata: 8 | name: default 9 | spec: 10 | nodeToNodeMeshEnabled: {{ plugins['calico']['fullmesh'] }} 11 | {%- if plugins['calico']['announceServices'] %} 12 | serviceClusterIPs: 13 | - cidr: {{ services['kubeadm']['networking']['serviceSubnet'] }} 14 | {%- endif %} 15 | asNumber: {{ plugins['calico']['defaultAsNumber'] }} 16 | 17 | 18 | {% if not plugins['calico']['fullmesh'] %} 19 | --- 20 | # This is for peering with route-reflectors 21 | 22 | apiVersion: crd.projectcalico.org/v1 23 | kind: BGPPeer 24 | metadata: 25 | name: peer-with-route-reflectors 26 | spec: 27 | nodeSelector: all() 28 | peerSelector: route-reflector == 'True' 29 | 30 | {% endif %} 31 | 32 | 33 | {%- for peer in plugins['calico']['globalBgpPeers'] -%} 34 | --- 35 | apiVersion: crd.projectcalico.org/v1 36 | kind: BGPPeer 37 | metadata: 38 | name: peer-with-route-reflectors-{{ peer['as'] }}-{{ peer['ip'] }} 39 | spec: 40 | asNumber: {{ peer['as'] }} 41 | peerIP: {{ peer['ip'] }} 42 | {%- endfor %} 43 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calico-typha-metrics.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: calico-typha-metrics 5 | namespace: kube-system 6 | labels: 7 | k8s-app: calico-typha-metrics 8 | spec: 9 | clusterIP: None 10 | selector: 11 | k8s-app: calico-typha 12 | ports: 13 | - name: metrics 14 | port: 9093 15 | targetPort: 9093 16 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/calicoctl.cfg.j2: -------------------------------------------------------------------------------- 1 | apiVersion: projectcalico.org/v3 2 | kind: CalicoAPIConfig 3 | metadata: 4 | spec: 5 | datastoreType: "kubernetes" 6 | kubeconfig: "/root/.kube/config" 7 | -------------------------------------------------------------------------------- /kubemarine/templates/plugins/dashboard-ingress.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | {{ plugins['kubernetes-dashboard']['ingress']|toyaml }} 5 | -------------------------------------------------------------------------------- /kubemarine/version: -------------------------------------------------------------------------------- 1 | v0.37.0 2 | -------------------------------------------------------------------------------- /requirements-pyinstaller.txt: -------------------------------------------------------------------------------- 1 | pyinstaller==6.6.0 2 | # Pinned version is used because scripts/ci/custom-hooks/hook-cryptography.py 3 | # relies on internal implementation of `pyinstaller-hooks-contrib`. 4 | # Need to regenerate scripts/ci/custom-hooks/hook-cryptography.py each time the version is upgraded. 5 | pyinstaller-hooks-contrib==2024.6 6 | -------------------------------------------------------------------------------- /scripts/ci/build_binary.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import fileinput 16 | import subprocess 17 | import sys 18 | from typing import List 19 | import tarfile 20 | 21 | # pylint: disable=bad-builtin 22 | 23 | PIP_VERSION = "24.0" 24 | 25 | 26 | def call(args: List[str]) -> None: 27 | return_code = subprocess.call(args) 28 | if return_code != 0: 29 | sys.exit(return_code) 30 | 31 | 32 | # Copy ipip_check from package 33 | with open('kubemarine/version', 'r', encoding='utf-8') as version_file: 34 | version = version_file.readline().split('\n')[0].split('v')[1] 35 | 36 | with tarfile.open(f"dist/kubemarine-{version}.tar.gz") as arch: 37 | file_obj = arch.extractfile(f"kubemarine-{version}/kubemarine/resources/scripts/ipip_check.gz") 38 | with open('kubemarine/resources/scripts/ipip_check.gz', 'wb') as binary: 39 | if file_obj is not None: 40 | binary.write(file_obj.read()) 41 | 42 | # Install exact version of pip, because 'scripts/ci/install_package.py' relies on its internal implementation. 43 | # Note that downgrade is possible. 44 | # https://github.com/pypa/pip/blob/24.0/docs/html/user_guide.rst#using-pip-from-your-program 45 | call([sys.executable, '-m', 'pip', 'install', f'pip=={PIP_VERSION}']) 46 | 47 | target_arch = None 48 | if len(sys.argv) > 1: 49 | target_arch = sys.argv[1] 50 | 51 | install_package = [sys.executable, 'scripts/ci/install_package.py'] 52 | if target_arch: 53 | install_package.append(target_arch) 54 | call(install_package) 55 | 56 | if target_arch == 'arm64': 57 | # universal2 build for macOS is not really universal, and this won't be fixed 58 | # https://sourceforge.net/p/ruamel-yaml-clib/tickets/20/ 59 | # At the same time, the dependency is optional and is going to be removed. 60 | # https://sourceforge.net/p/ruamel-yaml-clib/tickets/33/#0443 61 | call(['pip', 'uninstall', '-y', 'ruamel.yaml.clib']) 62 | 63 | # To avoid ambiguity, remove Kubemarine package to surely run PyInstaller on sources. 64 | call(['pip', 'uninstall', '-y', 'kubemarine']) 65 | call(['pip', 'install', '-r', 'requirements-pyinstaller.txt']) 66 | 67 | if target_arch: 68 | with fileinput.FileInput('kubemarine.spec', inplace=True) as file: 69 | for line in file: 70 | if "target_arch = None" == line.strip(): 71 | line = f"target_arch = '{target_arch}'\n" 72 | print(line, end='') 73 | 74 | call(['pyinstaller', 'kubemarine.spec', '--noconfirm']) 75 | -------------------------------------------------------------------------------- /scripts/ci/custom-hooks/hook-cryptography.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from typing import List, Tuple 16 | 17 | from PyInstaller.utils.hooks import copy_metadata 18 | 19 | datas = copy_metadata('cryptography') 20 | 21 | # Starting from cryptography 40.0.0, PyInstaller is no longer able to build the binary for macOS arm64 platform 22 | # being on macOS x86_64 platform due to failing _pyinstaller_hooks_contrib/hooks/stdhooks/hook-cryptography.py 23 | # This script provides custom effectively equal implementation of the hook. 24 | 25 | # Use the following commented out script to regenerate `binaries` and `hiddenimports`, 26 | # being on the macOS arm64 platform. 27 | 28 | # import importlib.machinery 29 | # import os 30 | # import _pyinstaller_hooks_contrib.hooks.stdhooks 31 | # 32 | # hook_filename = os.path.join(os.path.dirname(_pyinstaller_hooks_contrib.hooks.stdhooks.__file__), 'hook-cryptography.py') 33 | # mod_loader = importlib.machinery.SourceFileLoader('hook-cryptography', hook_filename) 34 | # mod = mod_loader.load_module() 35 | # 36 | # lf = '\n' 37 | # print(f"binaries: List[Tuple[str, str]] = [{lf}{f',{lf}'.join(map(lambda b: f' ({b[0]!r}, {b[1]!r})', mod.binaries))}{lf}]") 38 | # print(f"hiddenimports = [{lf}{f',{lf}'.join(map(lambda i: f' {i!r}', mod.hiddenimports))}{lf}]") 39 | 40 | binaries: List[Tuple[str, str]] = [ 41 | 42 | ] 43 | hiddenimports = [ 44 | 'cryptography.hazmat.backends', 45 | 'cryptography.hazmat.backends.openssl', 46 | 'cryptography.hazmat.backends.openssl.aead', 47 | 'cryptography.hazmat.backends.openssl.backend', 48 | 'cryptography.hazmat.backends.openssl.ciphers', 49 | 'cryptography.hazmat.backends.openssl.decode_asn1', 50 | 'cryptography.hazmat.bindings.openssl', 51 | 'cryptography.hazmat.bindings.openssl._conditional', 52 | 'cryptography.hazmat.bindings.openssl.binding', 53 | '_cffi_backend' 54 | ] 55 | -------------------------------------------------------------------------------- /scripts/ci/install_package.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # The script installs Kubemarine package from dist/*.whl with its dependencies. 16 | # The 1st optional argv parameter define macOS target architecture. 17 | 18 | import glob 19 | import sys 20 | from importlib.metadata import version 21 | from typing import Tuple 22 | 23 | # pylint: disable=bad-builtin,wrong-import-position 24 | 25 | expected_pip_version = '24.0' 26 | pip_version = version('pip') 27 | assert pip_version == expected_pip_version,\ 28 | f"The script relies on internal implementation of pip and was tested on pip=={expected_pip_version}. " \ 29 | f"To support pip=={pip_version}, the script should be manually adopted." 30 | 31 | 32 | from pip._internal.cli.main import main as pip_main 33 | 34 | 35 | def patch_mac_ver(mac_arch: str) -> None: 36 | """ 37 | Patch platform.mac_ver() to return the target (in general, non-native) macOS architecture. 38 | Pip will choose wheels suitable for the target architecture when installing the packages. 39 | 40 | See pip._internal.models.target_python.TargetPython.get_tags() and downstream methods. 41 | 42 | For non-native target architecture such packages will obviously not work, 43 | and can only be used to be included in Kubemarine executable using PyInstaller. 44 | 45 | :param mac_arch: Target macOS architecture 46 | """ 47 | import platform 48 | 49 | assert platform.system() == 'Darwin', "Target architecture is allowed only on macOS platform" 50 | assert mac_arch in ('x86_64', 'arm64'), f"Unexpected target architecture {mac_arch!r}" 51 | 52 | mac_ver_orig = platform.mac_ver 53 | 54 | def mac_ver(release: str = '', versioninfo: Tuple[str, str, str] = ('', '', ''), machine: str = '') \ 55 | -> Tuple[str, Tuple[str, str, str], str]: 56 | result = mac_ver_orig(release, versioninfo, machine) 57 | return result[0], result[1], mac_arch 58 | 59 | platform.mac_ver = mac_ver 60 | 61 | 62 | mac_arch = None 63 | if len(sys.argv) > 1: 64 | mac_arch = sys.argv[1] 65 | 66 | 67 | pip_args = ['install'] 68 | if mac_arch: 69 | patch_mac_ver(mac_arch) 70 | # Target architecture can be non-native. 71 | # We should not allow building of packages from sources, thus force pip use wheels. 72 | pip_args.extend(['--only-binary', ':all:']) 73 | 74 | pip_args.append(glob.glob('dist/*.whl')[0]) 75 | 76 | sys.exit(pip_main(pip_args)) 77 | -------------------------------------------------------------------------------- /scripts/thirdparties/.synccache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/scripts/thirdparties/.synccache/.gitkeep -------------------------------------------------------------------------------- /scripts/thirdparties/src/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /scripts/thirdparties/src/shell.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import subprocess 17 | import sys 18 | from typing import List 19 | from urllib import request 20 | 21 | # pylint: disable=bad-builtin 22 | 23 | SYNC_CACHE = os.path.abspath(f"{__file__}/../../.synccache") 24 | TEMP_FILE = os.path.join(SYNC_CACHE, "tempfile") 25 | 26 | 27 | def info(message: str) -> None: 28 | if os.name != 'nt': 29 | message = f'\033[1;32m{message}\033[0m' 30 | print(message) 31 | 32 | 33 | def fatal(message: str) -> None: 34 | print(f'\033[1;31m{message}\033[0m') 35 | sys.exit(1) 36 | 37 | 38 | def run(args: List[str]) -> str: 39 | print(f" > {' '.join(args)}") 40 | return subprocess.run(args, capture_output=True, check=True) \ 41 | .stdout.decode('utf-8') 42 | 43 | 44 | def curl(source: str, filepath: str) -> None: 45 | if os.path.exists(filepath): 46 | os.remove(filepath) 47 | 48 | request.urlretrieve(source, filepath) 49 | -------------------------------------------------------------------------------- /scripts/thirdparties/src/software/defaults.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from kubemarine.core import utils 16 | 17 | # pylint: disable=bad-builtin 18 | 19 | YAML = utils.yaml_structure_preserver() 20 | RESOURCE_PATH = utils.get_internal_resource_path("resources/configurations/defaults.yaml") 21 | 22 | 23 | class KubemarineDefaults: 24 | def __init__(self) -> None: 25 | with utils.open_internal(RESOURCE_PATH) as stream: 26 | self._defaults = YAML.load(stream) 27 | 28 | def default_version(self) -> str: 29 | return str(self._defaults['services']['kubeadm']['kubernetesVersion']) 30 | -------------------------------------------------------------------------------- /scripts/thirdparties/sync.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | # pylint: disable=bad-builtin,wrong-import-position 19 | 20 | # Ensure to take Kubemarine modules from the project root. 21 | # !!! This should be a very first line of the script !!! 22 | ROOT = os.path.abspath(f"{__file__}/../../..") 23 | sys.path.insert(0, ROOT) 24 | 25 | import argparse 26 | import platform 27 | 28 | from src.compatibility import KubernetesVersions 29 | from src.run import Synchronization 30 | from src.shell import fatal 31 | from src.software import InternalCompatibility, UpgradeConfig 32 | from src.software.kubernetes_images import KubernetesImagesResolver 33 | from src.software.plugins import ManifestResolver, ManifestsEnrichment 34 | from src.software.thirdparties import ThirdpartyResolver 35 | from src.software.defaults import KubemarineDefaults 36 | 37 | if __name__ == '__main__': 38 | if platform.system() != 'Linux': 39 | fatal("The tool can be run only on Linux.") 40 | 41 | parser = argparse.ArgumentParser(description="Tool to synchronize thirdparties compatibility mappings") 42 | 43 | parser.add_argument('--refresh-manifests', 44 | action='store_true', 45 | help='Always download and actualize plugin manifests') 46 | 47 | args = parser.parse_args() 48 | Synchronization( 49 | KubemarineDefaults(), 50 | InternalCompatibility(), 51 | KubernetesVersions(), 52 | KubernetesImagesResolver(), 53 | ManifestResolver(refresh=args.refresh_manifests), 54 | ThirdpartyResolver(), 55 | ManifestsEnrichment(), 56 | UpgradeConfig(), 57 | ).run() 58 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import re 16 | 17 | from setuptools import setup 18 | 19 | 20 | def read(path): 21 | with open(path, 'r', encoding='utf-8') as f: 22 | return f.read() 23 | 24 | 25 | VERSION = read("kubemarine/version").strip() 26 | 27 | README = read("README.md") 28 | # Special case to refer to anchor within the current README page should be translated to explicit README referring. 29 | README = re.sub( 30 | r'\[(.*?)]\((#.*?)\)', 31 | rf'[\1](https://github.com/Netcracker/KubeMarine/blob/{VERSION}/README.md\2)', 32 | README 33 | ) 34 | # Replace all relative links (not starting with http[s]://) to absolute referring to specific version on GitHub 35 | README = re.sub( 36 | r'\[(.*?)]\((?!https?://)(.*?)\)', 37 | rf'[\1](https://github.com/Netcracker/KubeMarine/blob/{VERSION}/\2)', 38 | README 39 | ) 40 | 41 | # Though deprecated, it seems to be the only way to provide shell scripts. 42 | SCRIPTS=["bin/kubemarine.cmd", "bin/kubemarine"] 43 | 44 | setup( 45 | scripts=SCRIPTS, 46 | version=VERSION, 47 | long_description=README, 48 | long_description_content_type='text/markdown', 49 | url='https://github.com/Netcracker/KubeMarine' 50 | ) 51 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2021-2022 NetCracker Technology Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | if __name__ == '__main__': 18 | pass 19 | -------------------------------------------------------------------------------- /test/resources/fetch_os_versions_example.txt: -------------------------------------------------------------------------------- 1 | CentOS Linux release 7.6.1810 (Core) 2 | NAME="CentOS Linux" 3 | VERSION="7 (Core)" 4 | ID="centos" 5 | ID_LIKE="rhel fedora" 6 | VERSION_ID="7" 7 | PRETTY_NAME="CentOS Linux 7 (Core)" 8 | ANSI_COLOR="0;31" 9 | CPE_NAME="cpe:/o:centos:centos:7" 10 | HOME_URL="https://www.centos.org/" 11 | BUG_REPORT_URL="https://bugs.centos.org/" 12 | 13 | CENTOS_MANTISBT_PROJECT="CentOS-7" 14 | CENTOS_MANTISBT_PROJECT_VERSION="7" 15 | REDHAT_SUPPORT_PRODUCT="centos" 16 | REDHAT_SUPPORT_PRODUCT_VERSION="7" 17 | 18 | CentOS Linux release 7.6.1810 (Core) 19 | CentOS Linux release 7.6.1810 (Core) 20 | -------------------------------------------------------------------------------- /test/unit/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /test/unit/core/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2021-2022 NetCracker Technology Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | if __name__ == '__main__': 18 | pass 19 | -------------------------------------------------------------------------------- /test/unit/plugins/test_templates/test_template1.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/test/unit/plugins/test_templates/test_template1.yaml -------------------------------------------------------------------------------- /test/unit/plugins/test_templates/test_template2.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/test/unit/plugins/test_templates/test_template2.yaml -------------------------------------------------------------------------------- /test/unit/plugins/test_templates/test_template3.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netcracker/KubeMarine/9ce4775b89a0a80b7c0ba0c308be6715f9aa175b/test/unit/plugins/test_templates/test_template3.yaml -------------------------------------------------------------------------------- /test/unit/test_admission.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import re 15 | import unittest 16 | from copy import deepcopy 17 | 18 | from kubemarine import demo 19 | from kubemarine.core import errors 20 | 21 | 22 | class EnrichmentValidation(unittest.TestCase): 23 | def setUp(self): 24 | self.inventory = demo.generate_inventory(**demo.ALLINONE) 25 | 26 | def _inventory(self): 27 | self.inventory['rbac'] = { 28 | 'pss': { 29 | 'pod-security': 'enabled' 30 | } 31 | } 32 | return self.inventory['rbac']['pss'] 33 | 34 | def _new_cluster(self): 35 | return demo.new_cluster(deepcopy(self.inventory)) 36 | 37 | def test_unexpected_admission(self): 38 | inventory = demo.generate_inventory(**demo.ALLINONE) 39 | inventory['rbac'] = { 40 | 'admission': 'unexpected' 41 | } 42 | with self.assertRaisesRegex(errors.FailException, r"Value should be one of \['pss']"): 43 | demo.new_cluster(inventory) 44 | 45 | def test_unexpected_pod_security(self): 46 | self._inventory()['pod-security'] = 'unexpected' 47 | with self.assertRaisesRegex(errors.FailException, r"Value should be one of \['enabled', 'disabled']"): 48 | self._new_cluster() 49 | 50 | def test_pss_invalid_profile(self): 51 | self._inventory()['defaults'] = {'enforce': 'unexpected'} 52 | with self.assertRaisesRegex(errors.FailException, r"Value should be one of \['privileged', 'baseline', 'restricted']"): 53 | self._new_cluster() 54 | 55 | def test_pss_defaults_verify_version(self): 56 | self._inventory()['defaults'] = {'enforce-version': 'not a version'} 57 | self.inventory['services'].setdefault('kubeadm', {})['kubernetesVersion'] = 'v1.30.1' 58 | with self.assertRaisesRegex(Exception, re.escape( 59 | f"Incorrect enforce-version 'not a version', " 60 | f"valid version (for example): v1.30")): 61 | self._new_cluster() 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /test/unit/test_check_paas.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import unittest 16 | 17 | from kubemarine import demo 18 | from kubemarine.core import errors 19 | 20 | 21 | class EnrichmentValidation(unittest.TestCase): 22 | def setUp(self): 23 | self.inventory = demo.generate_inventory(**demo.MINIHA) 24 | self.context = demo.create_silent_context(['fake.yaml'], procedure='check_paas') 25 | self.check_paas = demo.generate_procedure_inventory('check_paas') 26 | self.check_paas['geo-monitor'] = {} 27 | 28 | def _new_cluster(self): 29 | return demo.new_cluster(self.inventory, procedure_inventory=self.check_paas, context=self.context) 30 | 31 | def test_geo_check_missed_namespace(self): 32 | self.check_paas['geo-monitor']['service'] = 's' 33 | with self.assertRaisesRegex(errors.FailException, r"'namespace' is a required property"): 34 | self._new_cluster() 35 | 36 | def test_geo_check_missed_service(self): 37 | self.check_paas['geo-monitor']['namespace'] = 'n' 38 | with self.assertRaisesRegex(errors.FailException, r"'service' is a required property"): 39 | self._new_cluster() 40 | 41 | def test_geo_check_valid(self): 42 | self.check_paas['geo-monitor']['service'] = 's' 43 | self.check_paas['geo-monitor']['namespace'] = 'n' 44 | self._new_cluster() 45 | 46 | 47 | if __name__ == '__main__': 48 | unittest.main() 49 | -------------------------------------------------------------------------------- /test/unit/test_config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import unittest 16 | 17 | from kubemarine.core import static 18 | from kubemarine.procedures import config 19 | 20 | 21 | class ProcedureConfigTest(unittest.TestCase): 22 | def test_make_config(self): 23 | """Does basic smoke test that kubemarine.procedures.config.make_config() exits successfully""" 24 | cfg = config.make_config() 25 | self.assertEqual(list(static.KUBERNETES_VERSIONS['compatibility_map']), list(cfg['kubernetes'])) 26 | 27 | 28 | if __name__ == '__main__': 29 | unittest.main() 30 | -------------------------------------------------------------------------------- /test/unit/test_kubernetes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2022 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import unittest 16 | from textwrap import dedent 17 | 18 | from kubemarine import demo, kubernetes 19 | from kubemarine.core import summary 20 | 21 | 22 | class TestInventoryValidation(unittest.TestCase): 23 | def test_schedule_running_nodes_report(self): 24 | cluster = demo.new_cluster(demo.generate_inventory(**demo.ALLINONE)) 25 | stdout = dedent( 26 | """\ 27 | items: 28 | - metadata: 29 | labels: 30 | node-role.kubernetes.io/control-plane: "" 31 | node-role.kubernetes.io/worker: worker 32 | name: k8s-control-plane-1 33 | status: 34 | conditions: 35 | - status: "False" 36 | type: Ready 37 | - status: "True" 38 | type: NetworkUnavailable 39 | - metadata: 40 | labels: 41 | node-role.kubernetes.io/control-plane: "" 42 | node-role.kubernetes.io/worker: worker 43 | name: k8s-control-plane-2 44 | status: 45 | conditions: 46 | - status: "True" 47 | type: Ready 48 | - status: "False" 49 | type: NetworkUnavailable 50 | - metadata: 51 | labels: 52 | node-role.kubernetes.io/worker: worker 53 | name: k8s-control-plane-3 54 | status: 55 | conditions: 56 | - status: "True" 57 | type: Ready 58 | - status: "True" 59 | type: NetworkUnavailable 60 | """.rstrip() 61 | ) 62 | get_nodes = demo.create_nodegroup_result(cluster.nodes['control-plane'], stdout=stdout) 63 | cluster.fake_shell.add(get_nodes, 'sudo', [kubernetes.get_nodes_description_cmd()]) 64 | kubernetes.exec_running_nodes_report(cluster) 65 | summary_report = cluster.context.get('summary_report') 66 | self.assertEqual( 67 | { 68 | summary.SummaryItem.CONTROL_PLANES: "1/2", 69 | summary.SummaryItem.WORKERS: "1/3", 70 | }, 71 | summary_report 72 | ) 73 | 74 | 75 | if __name__ == '__main__': 76 | unittest.main() 77 | -------------------------------------------------------------------------------- /test/unit/tools/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /test/unit/tools/thirdparties/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2023 NetCracker Technology Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | --------------------------------------------------------------------------------