├── .coveragerc ├── .github └── workflows │ ├── build.yml │ ├── checks.yml │ ├── codeql-analysis.yml │ └── deploy.yml ├── .gitignore ├── .gitpod.Dockerfile ├── .gitpod.yml ├── .vscode └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── DEVELOPING.md ├── Dockerfile ├── LICENSE ├── MANIFEST.in ├── README.md ├── bin ├── __init__.py └── cli.py ├── build_ide.sh ├── cli_dev.sh ├── contributors.txt ├── docs ├── Makefile ├── README-INSTALL-HPECP-HOSTS.md ├── make.bat ├── modules.rst └── source │ ├── _static │ └── cli_example.gif │ ├── cli.rst │ ├── cli_overview.rst │ ├── conf.py │ ├── github.rst │ ├── hpecp.base_resource.rst │ ├── hpecp.client.rst │ ├── hpecp.config.rst │ ├── hpecp.exceptions.rst │ ├── hpecp.gateway.rst │ ├── hpecp.k8s_cluster.rst │ ├── hpecp.k8s_worker.rst │ ├── hpecp.license.rst │ ├── hpecp.lock.rst │ ├── hpecp.rst │ ├── hpecp.tag.rst │ ├── hpecp.tenant.rst │ ├── index.rst │ ├── installation.rst │ ├── license.rst │ └── logging.rst ├── git_env_password.sh ├── gitpod.env ├── hpecp ├── __init__.py ├── base_resource.py ├── catalog.py ├── cli │ ├── __init__.py │ ├── base.py │ ├── catalog.py │ ├── config.py │ ├── datatap.py │ ├── epicworker.py │ ├── gateway.py │ ├── httpclient.py │ ├── install.py │ ├── k8scluster.py │ ├── k8sworker.py │ ├── license.py │ ├── lock.py │ ├── role.py │ ├── tenant.py │ └── user.py ├── cli_utils.py ├── client.py ├── config.py ├── datatap.py ├── epic_worker.py ├── exceptions.py ├── gateway.py ├── install.py ├── k8s_cluster.py ├── k8s_worker.py ├── license.py ├── lock.py ├── logger.py ├── role.py ├── tenant.py └── user.py ├── latest.package.json ├── pre_push_verifications.sh ├── pyproject.toml ├── requirements.txt ├── run_ide.sh ├── setup.cfg ├── setup.py ├── tests ├── _HPECP-REST-API-SOAPUI.xml ├── __init__.py ├── base.py ├── base_resource_test.py ├── catalog_mock_api_responses.py ├── catalog_test.py ├── cli_mock_api_responses.py ├── cli_test.py ├── client_mock_api_responses.py ├── client_test.py ├── config_mock_api_responses.py ├── config_test.py ├── gateway_mock_api_responses.py ├── gateway_test.py ├── k8s_cluster_mock_api_responses.py ├── k8s_cluster_test.py ├── k8s_worker_mock_api_responses.py ├── k8s_worker_test.py ├── license_mock_api_responses.py ├── license_test.py ├── lock_mock_api_responses.py ├── lock_test.py ├── role_mock_api_responses.py ├── role_test.py ├── tenant_mock_api_responses.py ├── tenant_test.py ├── user_mock_api_responses.py └── user_test.py ├── theia_git_setup.sh ├── tox.ini └── utils ├── hpecp_cli_conf.sh ├── hpecp_configure.sh ├── hpecp_controller_ip.sh ├── hpecp_firewall.sh ├── hpecp_proxy.sh ├── hpecp_start.sh ├── hpecp_status.sh └── hpecp_stop.sh /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | relative_files = True 4 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build & Test 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | push: 8 | branches: 9 | - master 10 | schedule: 11 | # Run a build twice a day (12.00 AM and 12.00 PM) 12 | - cron: '0 0-23/12 * * *' 13 | 14 | jobs: 15 | test: 16 | name: Build & Test 17 | runs-on: ubuntu-latest 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | python-version: [2.7, 3.5, 3.6, 3.7, 3.8] 22 | 23 | steps: 24 | - name: Checkout ${{ github.sha }} from repository ${{ github.repository }} 25 | uses: actions/checkout@v2 26 | - name: Set up Python ${{ matrix.python-version }} 27 | uses: actions/setup-python@v2 28 | with: 29 | python-version: ${{ matrix.python-version }} 30 | - name: Install requirements 31 | run: | 32 | python -m pip install --upgrade pip 33 | pip install -r requirements.txt 34 | pip install tox-gh-actions 35 | pip install coverage mock tox 36 | - name: Build 37 | run: | 38 | python setup.py install 39 | - name: Test with tox 40 | run: | 41 | tox 42 | - name: Test coverage 43 | run: | 44 | coverage run --source hpecp,bin setup.py test 45 | coverage report -m 46 | - name: Coverage 47 | uses: AndreMiras/coveralls-python-action@develop 48 | with: 49 | github-token: g0waCcM28o3gLyuF0JbAmWRbYl1iS9lyp 50 | debug: true 51 | 52 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Code Checks 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | push: 8 | branches: 9 | - master 10 | schedule: 11 | # Run checks twice a day (12.00 AM and 12.00 PM) 12 | - cron: '0 0-23/12 * * *' 13 | 14 | jobs: 15 | check: 16 | name: Code Checks 17 | runs-on: ubuntu-latest 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | python-version: [3.8] 22 | 23 | steps: 24 | - name: Checkout ${{ github.sha }} from repository ${{ github.repository }} 25 | uses: actions/checkout@v2 26 | - name: Set up Python ${{ matrix.python-version }} 27 | uses: actions/setup-python@v2 28 | with: 29 | python-version: ${{ matrix.python-version }} 30 | - name: Install requirements 31 | run: | 32 | python -m pip install --upgrade pip 33 | pip install coverage 34 | pip install flake8 flake8-docstrings flake8-per-file-ignores==0.8.1 35 | pip uninstall -y typing 36 | pip install black 37 | - name: Run linter (flake8) 38 | run: | 39 | # stop the build if there are Python syntax errors or undefined names 40 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 41 | flake8 --exclude hpecp/role.py --docstring-convention numpy bin/ hpecp/ 42 | - name: Check code formatting (black) 43 | run: | 44 | black --check hpecp/ tests/ bin/ 45 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '37 0 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | name: Versioning 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 0 16 | - name: Python Semantic Release 17 | uses: relekang/python-semantic-release@master 18 | with: 19 | github_token: ${{ secrets.GITHUB_TOKEN }} 20 | pypi_token: ${{ secrets.PYPI_TOKEN }} 21 | - uses: actions/setup-python@v2 22 | with: 23 | python-version: 2.7 24 | - name: Install and Run Python 2.7 25 | run: | 26 | sudo apt-get install python3-setuptools 27 | python -c "print('*' * 80)" 28 | pip install hpecp 29 | python -c "print('*' * 80)" 30 | echo "Running 'hpecp version':" 31 | hpecp version 32 | python -c "print('*' * 80)" 33 | - uses: actions/setup-python@v2 34 | with: 35 | python-version: ${{ matrix.python-version }} 36 | - name: Install and Run Python 3.x 37 | run: | 38 | sudo apt-get install python3-setuptools python3-wheel 39 | python -c "print('*' * 80)" 40 | pip3 install hpecp 41 | python -c "print('*' * 80)" 42 | echo "Running 'hpecp version':" 43 | hpecp version 44 | python -c "print('*' * 80)" 45 | 46 | deploy: 47 | name: Deploy 48 | runs-on: ubuntu-latest 49 | strategy: 50 | fail-fast: false 51 | matrix: 52 | python-version: [3.8] 53 | 54 | steps: 55 | - name: Checkout ${{ github.sha }} from repository ${{ github.repository }} 56 | uses: actions/checkout@v2 57 | - name: Set up Python ${{ matrix.python-version }} 58 | uses: actions/setup-python@v2 59 | with: 60 | python-version: ${{ matrix.python-version }} 61 | - name: Install requirements 62 | run: | 63 | pip install tabulate 64 | pip install sphinx 65 | pip install six 66 | pip install polling 67 | - name: Build Docs 68 | run: | 69 | pip install -r requirements.txt 70 | cd docs 71 | make html 72 | touch ./build/html/.nojekyll 73 | - name: Deploy to GitHub Pages 74 | uses: JamesIves/github-pages-deploy-action@v4.2.5 75 | with: 76 | ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} 77 | BRANCH: gh-pages 78 | FOLDER: docs/build/html 79 | CLEAN: true 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | docs/_build/ 103 | ipython_session.py 104 | vcap*.json 105 | .DS_Store 106 | 107 | hpecp.egg-info/ 108 | .coverage 109 | docs/build/ 110 | .noseids 111 | bin/hpecp 112 | .pytest_cache/ 113 | -------------------------------------------------------------------------------- /.gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | 3 | USER gitpod 4 | 5 | # Install custom tools, runtime, etc. using apt-get 6 | # For example, the command below would install "bastet" - a command line tetris clone: 7 | # 8 | # RUN sudo apt-get -q update && # sudo apt-get install -yq bastet && # sudo rm -rf /var/lib/apt/lists/* 9 | 10 | RUN sudo apt-get -q update && sudo apt-get install -y shellcheck tox python3-sphinx python3-pip 11 | 12 | ENV PATH=$PATH:/home/gitpod/.local/bin 13 | 14 | # setup the gitpod bundled python 15 | # RUN /home/gitpod/.pyenv/versions/2.7.*/bin/python2 -m pip install --upgrade pip 16 | RUN /home/gitpod/.pyenv/versions/3.8.*/bin/python3 -m pip install --upgrade pip 17 | 18 | # additional python versions 19 | RUN pyenv install 3.5.9 20 | RUN pyenv install 3.6.9 21 | RUN pyenv install 3.7.7 22 | 23 | # The following fails: build failed: cannot build base image: The command '/bin/sh -c pyenv install 3.9-dev' returned a non-zero code: 1 24 | # RUN pyenv install 3.9-dev 25 | 26 | # Allow pytest to discover tests 27 | RUN echo 'PYTHONPATH=/workspace/hpecp-python-library:$PYTHONPATH' > ~/.bashrc.d/40-pythonpath 28 | 29 | RUN \ 30 | wget https://s3.amazonaws.com/downloads.eviware/soapuios/5.5.0/SoapUI-5.5.0-linux-bin.tar.gz \ 31 | && sudo tar -xzf SoapUI-5.5.0-linux-bin.tar.gz -C /opt/ \ 32 | && rm SoapUI-5.5.0-linux-bin.tar.gz \ 33 | && sudo rm /opt/SoapUI-5.5.0/lib/groovy-all-2.4.4.jar \ 34 | && ( \ 35 | cd /tmp \ 36 | && wget https://dl.bintray.com/groovy/maven/apache-groovy-binary-2.4.19.zip \ 37 | && unzip /tmp/apache-groovy-binary-2.4.19.zip \ 38 | && sudo cp groovy-2.4.19/embeddable/groovy-all-2.4.19.jar /opt/SoapUI-5.5.0/lib/ \ 39 | ) 40 | # 41 | # More information: https://www.gitpod.io/docs/config-docker/ 42 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - before: gp env -e PYTHONPATH=/workspace/hpecp-python-library:$PYTHONPATH 3 | - command: /home/gitpod/.pyenv/versions/2.7.17/bin/python2 -m pip install -U pytest mock awscli -r ./requirements.txt --user && exit 4 | - command: /home/gitpod/.pyenv/versions/3.5.9/bin/python3 -m pip install -U pytest tox mock awscli flake8 flake8-docstrings -r ./requirements.txt --user && exit 5 | - command: /home/gitpod/.pyenv/versions/3.6.9/bin/python3 -m pip install -U pytest tox mock awscli black flake8 flake8-docstrings -r ./requirements.txt --user && exit 6 | - command: /home/gitpod/.pyenv/versions/3.7.7/bin/python3 -m pip install -U pytest tox mock awscli black flake8 flake8-docstrings -r ./requirements.txt --user && exit 7 | - command: /bin/python3 -m pip install -U pytest tox mock awscli black flake8 flake8-docstrings isort -r ./requirements.txt --user && ln -s -f $(which black) /bin && ln -s -f $(which isort) /bin && exit 8 | 9 | # - command: /home/gitpod/.pyenv/versions/3.9-dev/bin/python3 -m pip install -U pytest tox mock awscli black flake8 -r ./requirements.txt --user && exit 10 | - command: cd docs && make html && cd build/html && python3 -m http.server 9090 11 | - command: echo "Welcome" 12 | name: Static Server 13 | image: 14 | file: .gitpod.Dockerfile 15 | vscode: 16 | extensions: 17 | - littlefoxteam.vscode-python-test-adapter@0.3.16:tZ/6xOSSdKUaq6JCUVkD+A== 18 | - almenon.arepl@1.0.20:Uu7lIOwyLgmNWpTwCl/iqQ== 19 | - timonwong.shellcheck@0.9.0:hsU/Rd39aqPYowTqL+DbXg== 20 | - njpwerner.autodocstring@0.5.3:EBIOShg8dcmi8/snmYWYnw== 21 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "/**/*.pyc": true, 4 | "/**/__pycache__": true, 5 | "**/.classpath": true, 6 | "**/.project": true, 7 | "**/.settings": true, 8 | "**/.factorypath": true, 9 | ".tox": true, 10 | ".git": true, 11 | "hpecp.egg-info": true, 12 | ".pytest_cache": true, 13 | ".eggs": true 14 | }, 15 | "python.testing.nosetestArgs": [ 16 | "tests/library" 17 | ], 18 | "python.testing.pytestEnabled": true, 19 | "python.testing.unittestEnabled": false, 20 | "python.testing.nosetestsEnabled": false, 21 | "python.linting.pylintEnabled": false, 22 | "python.linting.flake8Enabled": true, 23 | "python.linting.flake8Args": [ 24 | "per-file-ignores=hpecp/__init__.py:F401", 25 | "--docstring-convention=numpy" 26 | ], 27 | "python.linting.enabled": true, 28 | "python.formatting.provider": "black", 29 | "python.formatting.blackPath": "/bin/black", 30 | "python.pythonPath": "/usr/bin/python", 31 | "python.envFile": "${workspaceFolder}/gitpod.env", 32 | "editor.formatOnSave": true, 33 | "files.insertFinalNewline": true, 34 | "git.alwaysSignOff": true, 35 | "autoDocstring.docstringFormat": "numpy" 36 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | We welcome and encourage community contributions to hpecp-python-library. 4 | 5 | ## Contributing 6 | 7 | The best way to directly collaborate with the project contributors is through GitHub: 8 | 9 | * If you want to contribute to our code by either fixing a problem or creating a new feature, please open a GitHub pull request. 10 | * If you want to raise an issue such as a defect, an enhancement request or a general issue, please open a GitHub issue. 11 | 12 | Before you start to code, we recommend discussing your plans through a GitHub issue, especially for more ambitious contributions. This gives other contributors a chance to point you in the right direction, give you feedback on your design, and help you find out if someone else is working on the same thing. 13 | 14 | Note that all patches from all contributors get reviewed. 15 | After a pull request is made, other contributors will offer feedback. If the patch passes review, a maintainer will accept it with a comment. 16 | When a pull request fails review, the author is expected to update the pull request to address the issue until it passes review and the pull request merges successfully. 17 | 18 | At least one review from a maintainer is required for all patches. 19 | 20 | ### Developer's Certificate of Origin 21 | 22 | All contributions must include acceptance of the DCO: 23 | 24 | > Developer Certificate of Origin Version 1.1 25 | > 26 | > Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 660 27 | > York Street, Suite 102, San Francisco, CA 94110 USA 28 | > 29 | > Everyone is permitted to copy and distribute verbatim copies of this 30 | > license document, but changing it is not allowed. 31 | > 32 | > Developer's Certificate of Origin 1.1 33 | > 34 | > By making a contribution to this project, I certify that: 35 | > 36 | > \(a) The contribution was created in whole or in part by me and I have 37 | > the right to submit it under the open source license indicated in the 38 | > file; or 39 | > 40 | > \(b) The contribution is based upon previous work that, to the best of my 41 | > knowledge, is covered under an appropriate open source license and I 42 | > have the right under that license to submit that work with 43 | > modifications, whether created in whole or in part by me, under the same 44 | > open source license (unless I am permitted to submit under a different 45 | > license), as indicated in the file; or 46 | > 47 | > \(c) The contribution was provided directly to me by some other person 48 | > who certified (a), (b) or (c) and I have not modified it. 49 | > 50 | > \(d) I understand and agree that this project and the contribution are 51 | > public and that a record of the contribution (including all personal 52 | > information I submit with it, including my sign-off) is maintained 53 | > indefinitely and may be redistributed consistent with this project or 54 | > the open source license(s) involved. 55 | 56 | ### Sign your work 57 | 58 | To accept the DCO, simply add this line to each commit message with your 59 | name and email address (git commit -s will do this for you): 60 | 61 | Signed-off-by: Jane Example 62 | 63 | For legal reasons, no anonymous or pseudonymous contributions are 64 | accepted. 65 | 66 | ## Submitting Code Pull Requests 67 | 68 | We encourage and support contributions from the community. No fix is too 69 | small. We strive to process all pull requests as soon as possible and 70 | with constructive feedback. If your pull request is not accepted at 71 | first, please try again after addressing the feedback you received. 72 | 73 | To make a pull request you will need a GitHub account. For help, see 74 | GitHub's documentation on forking and pull requests. 75 | -------------------------------------------------------------------------------- /DEVELOPING.md: -------------------------------------------------------------------------------- 1 | ### DEVELOPMENT ENVIRONMENT 2 | 3 | You can use gitpod - click [here](https://gitpod.io/#https://github.com/hpe-container-platform-community/hpecp-python-library/blob/master/DEVELOPING.md) to launch. 4 | 5 | - Installing the CLI in gitpod: 6 | 7 | ``` 8 | pip install -e . 9 | source <(hpecp autocomplete bash) # setup autocompletion 10 | hpecp configure-cli 11 | ``` 12 | 13 | ### Install from branch 14 | 15 | pip install --upgrade git+https://github.com/hpe-container-platform-community/hpecp-client@branch_name 16 | 17 | #### Mock Rest Service 18 | 19 | - First, open a terminal, then run: 20 | 21 | ``` 22 | /opt/SoapUI-5.5.0/bin/mockservicerunner.sh -m "REST MockService" tests/HPECP-REST-API-SOAPUI.xml 23 | ``` 24 | 25 | - Open another terminal and install the CLI (see instructions above) 26 | - Configure the cli: 27 | 28 | ``` 29 | cat > ~/.hpecp.conf < Tests` 88 | - Right Click `TEST` and select `PYTHON` 89 | - Click the `Circular Arrow` to find tests 90 | - Click the `Play Button` to test 91 | 92 | NOTE: click the `Python version` in the IDE footer bar to chose a different python version and repeat above steps. 93 | 94 | #### Terminal 95 | 96 | Run all tests **for all python versions** declared in tox.ini 97 | 98 | ``` 99 | tox 100 | ``` 101 | 102 | Run just the Python 2.7 tests 103 | 104 | ``` 105 | tox -e py27 106 | ``` 107 | 108 | Run all tests in a specific file: 109 | 110 | ``` 111 | tox -e py27 -- tests/library/client_test.py 112 | ``` 113 | 114 | Run a single test 115 | 116 | ``` 117 | tox -e py27 -- tests/library/client_test.py:TestCreateFromProperties.test_create_from_config_file_factory_method 118 | ``` 119 | 120 | ### COVERAGE 121 | 122 | Aim for 100% test coverage to ensure library will work with all specified python versions. 123 | 124 | ``` 125 | coverage erase && coverage run --source hpecp,bin setup.py test && coverage report -m 126 | ``` 127 | 128 | ### CODE QUALITY 129 | 130 | ``` 131 | pip3 install flake8 flake8-docstrings 132 | flake8 --docstring-convention numpy bin/ hpecp/ 133 | flake8 --ignore=D tests/ 134 | ``` 135 | 136 | ### FORMATTING 137 | 138 | ``` 139 | pip3 install black 140 | # automatically format hpecp folder 141 | black hpecp 142 | ``` 143 | 144 | ### RELEASING 145 | 146 | - Releasing is done using semantic releases. 147 | - The commit message will determine the release numbering, e.g. 148 | - `fix(sometext): fix message` - this will call a minor jump e.g. X.Y.Z to X.Y.Z+1 149 | - `feat(sometext): feature message` - this will call a major jump e.g. X.Y.Z to X.Y+1.Z 150 | 151 | 152 | ### TROUBLESHOOTING 153 | 154 | If you are unable to push from gitpod, naviate to: https://gitpod.io/access-control/ 155 | 156 | Ensure you select: 157 | 158 | - write public repos 159 | - read organisations 160 | 161 | Click Update and authorize on the gitpub page that opens. 162 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM theiaide/theia-python:latest 2 | 3 | ENV DEBIAN_FRONTEND noninteractive 4 | 5 | COPY requirements.txt /tmp 6 | 7 | RUN apt-get update \ 8 | && apt-get install -y vim yarn sudo python3-sphinx \ 9 | && apt-get install -y make build-essential libssl-dev zlib1g-dev \ 10 | libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev \ 11 | libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl git \ 12 | && apt-get clean \ 13 | && apt-get auto-remove -y \ 14 | && rm -rf /var/cache/apt/* \ 15 | && rm -rf /var/lib/apt/lists/* 16 | 17 | ## User account 18 | RUN adduser --disabled-password --gecos '' theia && \ 19 | adduser theia sudo && \ 20 | echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ 21 | chown -R theia:theia /home/theia && \ 22 | chmod 777 /home/theia 23 | 24 | RUN echo "Installing python modules in system python versions" \ 25 | && PY_PATHS="/usr/bin/python /usr/bin/python3 and /usr/local/bin/python3" \ 26 | && for v in ${PY_PATHS}; do echo "******* ${v} *******"; ${v} -m pip install --upgrade pip setuptools wheel; done \ 27 | && for v in ${PY_PATHS}; do echo "******* ${v} *******"; ${v} -m pip install --upgrade tox tox-pyenv ipython pylint pytest mock nose flake8 flake8-docstrings autopep8 jmespath fire jinja2; done \ 28 | && for v in ${PY_PATHS}; do ${v} -m pip install -r /tmp/requirements.txt; done \ 29 | && /usr/local/bin/python3 -m pip install -U black isort \ 30 | && ln -f -s /usr/local/bin/black /bin/ \ 31 | && ln -f -s /usr/local/bin/isort /bin/ 32 | 33 | # Setup ssh for git 34 | RUN test -d /home/theia/.ssh || mkdir /home/theia/.ssh \ 35 | && chmod 700 /home/theia/.ssh \ 36 | && touch /home/theia/.ssh/known_hosts \ 37 | && chmod 644 /home/theia/.ssh/known_hosts \ 38 | && chown -R theia /home/theia/.ssh \ 39 | && echo "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" > /home/theia/.ssh/known_hosts 40 | 41 | USER theia 42 | WORKDIR /home/theia 43 | 44 | RUN /bin/bash -c " \ 45 | git clone https://github.com/pyenv/pyenv.git ~/.pyenv \ 46 | && git clone https://github.com/momo-lab/xxenv-latest.git ~/.pyenv/plugins/latest \ 47 | && git clone https://github.com/doloopwhile/pyenv-register.git ~/.pyenv/plugins/pyenv-register" 48 | 49 | RUN echo 'export PYENV_ROOT="/home/theia/.pyenv"' >> ~/.bashrc \ 50 | && echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc \ 51 | && echo 'if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)"; fi' >> ~/.bashrc 52 | 53 | RUN cat ~/.bashrc 54 | 55 | RUN export PATH=/home/theia/.pyenv/bin:$PATH; \ 56 | eval "$(/home/theia/.pyenv/bin/pyenv init -)"; \ 57 | pyenv latest install 2.7 \ 58 | && pyenv latest install 3.5 \ 59 | && pyenv latest install 3.6 \ 60 | && pyenv latest install 3.7 \ 61 | && pyenv latest install 3.8 \ 62 | && pyenv install 3.9-dev \ 63 | && pyenv register /usr/bin/python \ 64 | && pyenv register /usr/bin/python3 \ 65 | && pyenv register /usr/local/bin/python3 \ 66 | && pyenv local $(pyenv versions --bare) \ 67 | && pyenv versions 68 | 69 | RUN echo "Installing python modules in pyenv python versions" \ 70 | && PY_PATHS=$(ls -1 /home/theia/.pyenv/versions/[0-9]*/bin/python?.?) \ 71 | && for v in ${PY_PATHS}; do echo "******* ${v} *******"; ${v} -m pip install --upgrade pip setuptools wheel; done \ 72 | && for v in ${PY_PATHS}; do echo "******* ${v} *******"; ${v} -m pip install --upgrade tox tox-pyenv ipython pylint pytest mock nose flake8 flake8-docstrings autopep8 jmespath fire jinja2; done \ 73 | && for v in ${PY_PATHS}; do ${v} -m pip install -r /tmp/requirements.txt; done 74 | 75 | 76 | WORKDIR /home/theia 77 | 78 | 79 | ENV PYTHONPATH=/home/project:$PYTHONPATH 80 | 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included 11 | in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include requirements.txt 3 | 4 | recursive-exclude * __pycache__ 5 | recursive-exclude * *.py[co] 6 | 7 | recursive-include bin/ *.py 8 | recursive-include hpecp/ *.py -------------------------------------------------------------------------------- /bin/__init__.py: -------------------------------------------------------------------------------- 1 | # noqa: D104 2 | -------------------------------------------------------------------------------- /build_ide.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker build . -t hpecp/hpecp-ide 4 | -------------------------------------------------------------------------------- /cli_dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | set -e 5 | 6 | pip install -e . 7 | 8 | hpecp autocomplete bash > ~/hpecp_completion.sh 9 | 10 | source ~/hpecp_completion.sh 11 | -------------------------------------------------------------------------------- /contributors.txt: -------------------------------------------------------------------------------- 1 | Chris Snow 2 | Bharath Narayan 3 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/README-INSTALL-HPECP-HOSTS.md: -------------------------------------------------------------------------------- 1 | Installing the CLI on HPE Container Platform Centos/Redhat Hosts 2 | --- 3 | 4 | There is an [issue](https://github.com/hpe-container-platform-community/hpecp-python-library/issues/45) 5 | with the version of Python installed by default on HPE CP. 6 | 7 | For demo environments, you can workaround this using pyenv: 8 | 9 | ``` 10 | sudo yum install -y gcc gcc-c++ make git patch openssl-devel zlib zlib-devel readline-devel sqlite-devel bzip2-devel libffi-devel 11 | git clone git://github.com/yyuu/pyenv.git ~/.pyenv 12 | echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc 13 | echo 'eval "$(pyenv init -)"' >> ~/.bashrc 14 | source ~/.bashrc 15 | pyenv install 3.6.10 16 | 17 | git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv 18 | echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc 19 | source ~/.bashrc 20 | 21 | pyenv virtualenv 3.6.10 my-3.6.10 22 | pyenv activate my-3.6.10 23 | 24 | pip install -U hpecp 25 | ``` 26 | 27 | Whenever you run the hpecp cli activate python 3.6.10 first, I.e. 28 | 29 | ``` 30 | pyenv activate my-3.6.10 31 | hpecp do_something 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | hpecp 2 | ===== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | hpecp -------------------------------------------------------------------------------- /docs/source/_static/cli_example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpe-container-platform-community/hpecp-python-library/6fb16af433663887768308e1e6eb9f408ef6bd9f/docs/source/_static/cli_example.gif -------------------------------------------------------------------------------- /docs/source/cli.rst: -------------------------------------------------------------------------------- 1 | cli module 2 | =================== 3 | 4 | .. automodule:: bin.cli 5 | :members: 6 | :undoc-members: 7 | 8 | -------------------------------------------------------------------------------- /docs/source/cli_overview.rst: -------------------------------------------------------------------------------- 1 | CLI Docs 2 | ======== 3 | 4 | Setup 5 | ----- 6 | 7 | Install the library: 8 | 9 | 10 | .. code-block:: bash 11 | 12 | pip3 install --upgrade hpecp 13 | 14 | 15 | Create a configuration file: 16 | 17 | .. code-block:: bash 18 | 19 | cat > ~/.hpecp.conf <>> aa8716be-bc74-4ffa-b838-d92e6934d224 39 | 40 | 41 | CLI Help 42 | -------- 43 | 44 | Run `hpecp` without any arguments to retrieve a list of command groups:: 45 | 46 | hpecp 47 | 48 | Returns:: 49 | 50 | NAME 51 | hpecp 52 | 53 | SYNOPSIS 54 | hpecp GROUP 55 | 56 | GROUPS 57 | GROUP is one of the following: 58 | 59 | gateway 60 | ... 61 | 62 | Similary to see a list of subcommands (e.g. for the gateway command):: 63 | 64 | hpecp gateway --help 65 | 66 | Returns:: 67 | 68 | NAME 69 | hpecp gateway 70 | 71 | SYNOPSIS 72 | hpecp gateway COMMAND 73 | 74 | COMMANDS 75 | COMMAND is one of the following: 76 | 77 | create_with_ssh_key 78 | Create a Gateway using SSH key authentication 79 | 80 | create_with_ssh_password 81 | Not yet implemented 82 | 83 | delete 84 | Retrieve a Gateway by Id 85 | 86 | get 87 | Retrieve a Gateway by Id 88 | ... 89 | 90 | And to see a subcommand's (e.g. get) arguments:: 91 | 92 | hpecp gateway get --help 93 | 94 | Returns:: 95 | 96 | NAME 97 | hpecp gateway get - Retrieve a Gateway by Id 98 | 99 | SYNOPSIS 100 | hpecp gateway get GATEWAY_ID 101 | 102 | DESCRIPTION 103 | Retrieve a Gateway by Id 104 | 105 | POSITIONAL ARGUMENTS 106 | GATEWAY_ID 107 | the id of the gateway with format: '/api/v1/workers/[0-9]+' 108 | 109 | FLAGS 110 | --output=OUTPUT 111 | how to display the output ['yaml'|'json'] 112 | 113 | Example 114 | ------- 115 | 116 | .. image:: _static/cli_example.gif 117 | :alt: CLI Example 118 | 119 | Autocompletion 120 | -------------- 121 | 122 | 123 | (this is currently broken - awaiting: https://github.com/google/python-fire/issues/255) 124 | 125 | The CLI supports auto completion, for bash use: 126 | 127 | .. code-block:: bash 128 | 129 | hpecp -- --completion bash > ~/.hpecp_completion 130 | echo source ~/.hpecp_completion >> ~/.bash_profile 131 | 132 | 133 | For zsh, or fish, change the command from `bash` to `zsh` or `fish` in the first command and 134 | add the completion script to your shell init script, `~/.zshrc` or `~/.config/fish/config.fish`. 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | 14 | import os 15 | import sys 16 | sys.path.insert(0, os.path.abspath('../../')) 17 | 18 | from bin import cli 19 | 20 | # don't skip __init__ class methods 21 | #def skip(app, what, name, obj, would_skip, options): 22 | # if name == "__init__": 23 | # return False 24 | # return would_skip 25 | # 26 | #def setup(app): 27 | # app.connect("autodoc-skip-member", skip) 28 | 29 | 30 | autodoc_default_options = { 31 | 'member-order': 'bysource' 32 | } 33 | 34 | master_doc = 'index' 35 | 36 | # Add toctree to sidebar. See https://stackoverflow.com/a/19007358/1033422 37 | html_sidebars = { '**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'] } 38 | 39 | 40 | # -- Project information ----------------------------------------------------- 41 | 42 | project = 'HPE Container Platform Python Library' 43 | copyright = '2020, Chris Snow' 44 | author = 'Chris Snow' 45 | 46 | 47 | # -- General configuration --------------------------------------------------- 48 | 49 | # Add any Sphinx extension module names here, as strings. They can be 50 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 51 | # ones. 52 | extensions = [ 53 | 'sphinx.ext.autodoc', 54 | 'sphinx.ext.viewcode' 55 | ] 56 | 57 | # Add any paths that contain templates here, relative to this directory. 58 | templates_path = ['_templates'] 59 | 60 | # List of patterns, relative to source directory, that match files and 61 | # directories to ignore when looking for source files. 62 | # This pattern also affects html_static_path and html_extra_path. 63 | exclude_patterns = [] 64 | 65 | 66 | # -- Options for HTML output ------------------------------------------------- 67 | 68 | # The theme to use for HTML and HTML Help pages. See the documentation for 69 | # a list of builtin themes. 70 | # 71 | html_theme = 'bizstyle' 72 | 73 | # Add any paths that contain custom static files (such as style sheets) here, 74 | # relative to this directory. They are copied after the builtin static files, 75 | # so a file named "default.css" will overwrite the builtin "default.css". 76 | html_static_path = ['_static'] -------------------------------------------------------------------------------- /docs/source/github.rst: -------------------------------------------------------------------------------- 1 | Source Repository 2 | ================= 3 | 4 | The source code for the python libary can be found at `Github `_ -------------------------------------------------------------------------------- /docs/source/hpecp.base_resource.rst: -------------------------------------------------------------------------------- 1 | hpecp.base\_resource module 2 | ========================= 3 | 4 | .. automodule:: hpecp.base_resource 5 | :show-inheritance: 6 | :members: 7 | :undoc-members: 8 | :exclude-members: next 9 | -------------------------------------------------------------------------------- /docs/source/hpecp.client.rst: -------------------------------------------------------------------------------- 1 | hpecp.client module 2 | =================== 3 | 4 | .. automodule:: hpecp.client 5 | :members: 6 | :undoc-members: 7 | :exclude-members: USER_DEFAULT_CONFIG_FILE 8 | 9 | -------------------------------------------------------------------------------- /docs/source/hpecp.config.rst: -------------------------------------------------------------------------------- 1 | hpecp.config module 2 | =================== 3 | 4 | .. automodule:: hpecp.config 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/hpecp.exceptions.rst: -------------------------------------------------------------------------------- 1 | hpecp.exceptions module 2 | ======================= 3 | 4 | .. automodule:: hpecp.exceptions 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/hpecp.gateway.rst: -------------------------------------------------------------------------------- 1 | hpecp.gateway module 2 | ========================= 3 | 4 | .. automodule:: hpecp.gateway 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | :exclude-members: next -------------------------------------------------------------------------------- /docs/source/hpecp.k8s_cluster.rst: -------------------------------------------------------------------------------- 1 | hpecp.k8s\_cluster module 2 | ========================= 3 | 4 | .. automodule:: hpecp.k8s_cluster 5 | :show-inheritance: 6 | :members: 7 | :undoc-members: 8 | :exclude-members: next 9 | -------------------------------------------------------------------------------- /docs/source/hpecp.k8s_worker.rst: -------------------------------------------------------------------------------- 1 | hpecp.k8s\_worker module 2 | ======================== 3 | 4 | .. automodule:: hpecp.k8s_worker 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/hpecp.license.rst: -------------------------------------------------------------------------------- 1 | hpecp.license module 2 | ==================== 3 | 4 | .. automodule:: hpecp.license 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/hpecp.lock.rst: -------------------------------------------------------------------------------- 1 | hpecp.lock module 2 | ================= 3 | 4 | .. automodule:: hpecp.lock 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/hpecp.rst: -------------------------------------------------------------------------------- 1 | .. _apidocs: 2 | 3 | Library API Docs 4 | ================ 5 | 6 | .. toctree:: 7 | :maxdepth: 4 8 | :caption: Completed APIs 9 | 10 | hpecp.client 11 | hpecp.license 12 | hpecp.lock 13 | hpecp.gateway 14 | hpecp.base_resource 15 | 16 | .. toctree:: 17 | :maxdepth: 4 18 | :caption: Work-in-progress APIs 19 | 20 | hpecp.k8s_worker 21 | hpecp.k8s_cluster 22 | hpecp.config 23 | hpecp.tag 24 | hpecp.tenant 25 | hpecp.exceptions 26 | 27 | CLI API Docs 28 | ================ 29 | 30 | .. toctree:: 31 | :maxdepth: 4 32 | 33 | cli -------------------------------------------------------------------------------- /docs/source/hpecp.tag.rst: -------------------------------------------------------------------------------- 1 | hpecp.tag module 2 | ================ 3 | 4 | .. automodule:: hpecp.tag 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/hpecp.tenant.rst: -------------------------------------------------------------------------------- 1 | hpecp.tenant module 2 | =================== 3 | 4 | .. automodule:: hpecp.tenant 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Overview 2 | ========= 3 | 4 | Python library and Command Line Interface (CLI) for HPE Container Platform (HPECP). 5 | 6 | This library is beta. The API of this library may be unstable and 7 | subject to change until this library reaches GA. 8 | 9 | Library Example 10 | --------------- 11 | 12 | Example basic usage with variables passed to client constructor: 13 | 14 | First :ref:`install ` the library - then from your python environment ... 15 | 16 | .. code-block:: python 17 | 18 | from hpecp import ContainerPlatformClient 19 | 20 | client = ContainerPlatformClient(username='admin', 21 | password='admin123', 22 | api_host='127.0.0.1', 23 | api_port=8080, 24 | use_ssl=True, 25 | verify_ssl='/certs/hpecp-ca-cert.pem') 26 | 27 | client.create_session() # Login 28 | 29 | client.k8s_cluster.list().tabulate(columns=['description', 'id']) 30 | 31 | Example basic usage with config file: 32 | 33 | .. code-block:: bash 34 | 35 | cat > ~/.hpecp.conf < ~/.hpecp.conf <` the CLI. After installing, the CLI will be available as `hpecp`: 73 | 74 | .. code-block:: bash 75 | 76 | hpecp license platform-id 77 | 78 | >>> aa8716be-bc74-4ffa-b838-d92e6934d224 79 | 80 | To find out what capabilities are available, enter: 81 | 82 | .. code-block:: bash 83 | 84 | hpecp help 85 | 86 | Contents 87 | ======== 88 | 89 | .. toctree:: 90 | :maxdepth: 0 91 | 92 | installation 93 | hpecp 94 | cli_overview 95 | logging 96 | github 97 | license 98 | 99 | 100 | -------------------------------------------------------------------------------- /docs/source/installation.rst: -------------------------------------------------------------------------------- 1 | .. _Installation: 2 | 3 | Installation 4 | ============ 5 | 6 | While this library is beta, it is recommended to install it with pip using the `--upgrade` flag so 7 | that you always get the latest version. 8 | 9 | Note that until the API of this library will be unstable and subject to change until this library becomes beta. 10 | 11 | .. code-block:: bash 12 | 13 | pip3 install --upgrade hpecp 14 | 15 | -------------------------------------------------------------------------------- /docs/source/license.rst: -------------------------------------------------------------------------------- 1 | .. _license: 2 | 3 | ============== 4 | MIT License 5 | ============== 6 | 7 | Copyright [2020] Hewlett Packard Enterprise Development LP 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a 10 | copy of this software and associated documentation files (the "Software"), 11 | to deal in the Software without restriction, including without limitation 12 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | and/or sell copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /docs/source/logging.rst: -------------------------------------------------------------------------------- 1 | Logging 2 | ======= 3 | 4 | Logging level 5 | ------------- 6 | 7 | Log level is controlled with the environment variable `LOG_LEVEL`. 8 | 9 | Typical valid values are `ERROR`, `WARNING`, `INFO`, `DEBUG` - the default value is `INFO`. 10 | 11 | - `INFO` = Significant Events 12 | - `DEBUG` = API Requests 13 | 14 | 15 | .. code-block:: bash 16 | 17 | export LOG_LEVEL=DEBUG 18 | hpecp license platform-id 19 | 20 | >>> 2020-05-12 12:58:00,251 - ContainerPlatformClient - DEBUG - ContainerPlatformClient() created with username['admin'] 21 | >>> 2020-05-12 12:58:00,923 - ContainerPlatformClient - DEBUG - REQ: license/get_platform_id : get https://35.163.22.120:8080/api/v1/license 22 | >>> 2020-05-12 12:58:01,571 - ContainerPlatformClient - DEBUG - RES: license/get_platform_id : get https://35.163.22.120:8080/api/v1/license : 200 {"state": "unlicensed", "_links": {"self": {"href": "/api/v1/license"}}, "uuid": "aa8716be-bc74-4ffa-b838-d92e6934d224"} 23 | >>> aa8716be-bc74-4ffa-b838-d92e6934d224 24 | 25 | See https://docs.python.org/3.7/howto/logging.html for much more info on logging. 26 | 27 | 28 | Logging Configuration 29 | --------------------- 30 | 31 | To change logging configuration, e.g. to log to a file, set the environment variable `HPECP_LOG_CONFIG_FILE` and provide a configuration file. 32 | 33 | Example: `HPECP_LOG_CONFIG_FILE=~/.hpecp_logging.conf`: 34 | 35 | .. code-block:: bash 36 | 37 | [loggers] 38 | keys=root,HPECP_CLI 39 | 40 | [handlers] 41 | keys=consoleHandler,fileHandler 42 | 43 | [formatters] 44 | keys=consoleFormatter,fileFormatter 45 | 46 | [logger_root] 47 | level=INFO 48 | handlers=consoleHandler,fileHandler 49 | 50 | [logger_HPECP_CLI] 51 | level=DEBUG 52 | handlers=fileHandler 53 | qualname=HPECP_CLI 54 | propagate=0 55 | 56 | [handler_consoleHandler] 57 | level=INFO 58 | class=StreamHandler 59 | formatter=consoleFormatter 60 | args=(os.devnull,) 61 | 62 | [handler_fileHandler] 63 | level=DEBUG 64 | class=FileHandler 65 | formatter=fileFormatter 66 | args=("/MY/LOG/FILE/LOCATION/hpecp.log","a") 67 | 68 | [formatter_consoleFormatter] 69 | format=%(asctime)s - %(name)s - %(levelname)s - %(message)s 70 | datefmt= 71 | 72 | [formatter_fileFormatter] 73 | format=%(asctime)s - %(name)s - %(levelname)s - %(message)s 74 | datefmt= 75 | 76 | See https://docs.python.org/3.7/howto/logging.html for much more info on logging. 77 | 78 | 79 | -------------------------------------------------------------------------------- /git_env_password.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $GIT_PASS 3 | -------------------------------------------------------------------------------- /gitpod.env: -------------------------------------------------------------------------------- 1 | PYTHONPATH=. -------------------------------------------------------------------------------- /hpecp/__init__.py: -------------------------------------------------------------------------------- 1 | """A python library for working with HPE Container Platform. 2 | 3 | .. moduleauthor:: Chris Snow 4 | 5 | """ 6 | 7 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a 10 | # copy of this software and associated documentation files (the "Software"), 11 | # to deal in the Software without restriction, including without limitation 12 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | # and/or sell copies of the Software, and to permit persons to whom the 14 | # Software is furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included 17 | # in all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | # OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | from __future__ import absolute_import 28 | 29 | from .client import ContainerPlatformClient 30 | from .exceptions import ( 31 | APIException, 32 | APIItemConflictException, 33 | APIItemNotFoundException, 34 | ContainerPlatformClientException, 35 | ) 36 | from .logger import Logger 37 | 38 | __version__ = "0.22.13" 39 | -------------------------------------------------------------------------------- /hpecp/cli/__init__.py: -------------------------------------------------------------------------------- 1 | """A python library for working with HPE Container Platform. 2 | 3 | .. moduleauthor:: Chris Snow 4 | 5 | """ 6 | 7 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a 10 | # copy of this software and associated documentation files (the "Software"), 11 | # to deal in the Software without restriction, including without limitation 12 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | # and/or sell copies of the Software, and to permit persons to whom the 14 | # Software is furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included 17 | # in all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | # OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /hpecp/cli/catalog.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import sys 26 | 27 | from hpecp import APIException 28 | from hpecp.exceptions import APIItemNotFoundException 29 | from textwrap import dedent 30 | from hpecp.catalog import Catalog 31 | from hpecp.cli import base 32 | 33 | 34 | class CatalogProxy(base.BaseProxy): 35 | """Proxy object to :py:attr:``.""" 36 | 37 | def __init__(self): 38 | """Create instance of proxy class with the client module name.""" 39 | super(CatalogProxy, self).new_instance("catalog", Catalog) 40 | 41 | def __dir__(self): 42 | """Return the CLI method names.""" 43 | return [ 44 | "get", 45 | "list", 46 | "delete", 47 | "examples", 48 | "wait_for_state", 49 | "refresh", 50 | "install", 51 | ] 52 | 53 | def delete(self, id): 54 | """Not implemented.""" 55 | raise AttributeError("'CatalogProxy' object has no attribute 'delete'") 56 | 57 | def refresh(self, catalog_id): 58 | """Refresh a catalog. 59 | 60 | Parameters 61 | ---------- 62 | catalog_id : str 63 | The ID of the catalog - format: '/api/v1/catalog/[0-9]+' 64 | 65 | Examples 66 | -------- 67 | > hpecp catalog refresh /api/v1/catalog/99 68 | 69 | """ 70 | try: 71 | base.get_client().catalog.refresh(catalog_id) 72 | 73 | # TODO: Report progress of the refresh workflow 74 | except AssertionError as ae: 75 | print(ae, file=sys.stderr) 76 | sys.exit(1) 77 | except (APIException, APIItemNotFoundException) as e: 78 | print(e.message, file=sys.stderr) 79 | sys.exit(1) 80 | 81 | def install(self, catalog_id): 82 | """Install a catalog. 83 | 84 | Parameters 85 | ---------- 86 | catalog_id : str 87 | The ID of the catalog - format: '/api/v1/catalog/[0-9]+' 88 | 89 | Examples 90 | -------- 91 | > hpecp catalog install /api/v1/catalog/99 92 | 93 | """ 94 | try: 95 | base.get_client().catalog.install(catalog_id) 96 | 97 | # TODO: Implement a way to check if the installation is actually 98 | # successful (and maybe report progress?) - wait_for_state()? 99 | except AssertionError as ae: 100 | print(ae, file=sys.stderr) 101 | sys.exit(1) 102 | except (APIException, APIItemNotFoundException) as e: 103 | print(e.message, file=sys.stderr) 104 | sys.exit(1) 105 | 106 | def examples(self): 107 | """Show examples for working with roles.""" 108 | print( 109 | dedent( 110 | """\ 111 | 112 | $ hpecp catalog list --query "[?state!='installed' && state!='installing'] | [*].[_links.self.href] | []" --output json 113 | ["/api/v1/catalog/24", "/api/v1/catalog/27", "/api/v1/catalog/14", "/api/v1/catalog/11", "/api/v1/catalog/28", "/api/v1/catalog/18"] 114 | 115 | $ hpecp catalog list --query "[?state!='installed' && state!='installing'] | [*].[_links.self.href] | []" --output text 116 | /api/v1/catalog/24 117 | /api/v1/catalog/27 118 | /api/v1/catalog/14 119 | /api/v1/catalog/11 120 | /api/v1/catalog/28 121 | /api/v1/catalog/18 122 | 123 | $ hpecp catalog list --query "[?state!='installed' && state!='installing'] | [*].[_links.self.href, distro_id]" --output text 124 | /api/v1/catalog/29 bluedata/spark240juphub7xssl 125 | /api/v1/catalog/11 bluedata/ubuntu16 126 | /api/v1/catalog/21 bluedata/cdh632multi 127 | /api/v1/catalog/2 bluedata/spark231juphub7xssl 128 | """ # noqa: E501 129 | ) 130 | ) 131 | -------------------------------------------------------------------------------- /hpecp/cli/config.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import json 26 | import jmespath 27 | import sys 28 | import yaml 29 | from textwrap import dedent 30 | 31 | from hpecp.cli import base 32 | from hpecp.cli_utils import TextOutput 33 | 34 | 35 | class ConfigProxy(object): 36 | """Proxy object to :py:attr:``.""" 37 | 38 | def __dir__(self): 39 | """Return the CLI method names.""" 40 | return ["examples", "get"] 41 | 42 | @base.intercept_exception 43 | def get(self, output="yaml", query=None): 44 | """Get the system config. 45 | 46 | :param output: how to display the output '[yaml|json|json-pp]' 47 | """ 48 | if output not in ["yaml", "json", "json-pp", "text"]: 49 | print( 50 | ( 51 | "'output' parameter must be 'yaml', 'json', " 52 | "'json-pp' or 'text'." 53 | ), 54 | file=sys.stderr, 55 | ) 56 | sys.exit(1) 57 | 58 | if output == "yaml" and query is not None: 59 | print( 60 | "output=yaml is not supported with the query parameter.", 61 | file=sys.stderr, 62 | ) 63 | sys.exit(1) 64 | 65 | response = base.get_client().config.get() 66 | 67 | if output == "yaml": 68 | print( 69 | yaml.dump( 70 | yaml.load( 71 | json.dumps(response), 72 | Loader=yaml.FullLoader, 73 | ) 74 | ) 75 | ) 76 | else: 77 | if query is None: 78 | data = response 79 | else: 80 | data = jmespath.search(str(query), response) 81 | 82 | if output == "json-pp": 83 | print(json.dumps(data, indent=4, sort_keys=True)) 84 | elif output == "text": 85 | print(TextOutput.dump(data)) 86 | else: 87 | print(json.dumps(data)) 88 | 89 | def examples(self): 90 | """Show examples for working with roles.""" 91 | print( 92 | dedent( 93 | """\ 94 | 95 | $ hpecp config get --query 'objects.[bds_global_version]' --output text 96 | 5.1.1 97 | 98 | $ hpecp config get --query 'objects.[bds_global_version, bds_global_buildnumber]' --output text 99 | 5.1.1 100 | 2347 101 | 102 | """ # noqa: E501 103 | ) 104 | ) 105 | -------------------------------------------------------------------------------- /hpecp/cli/datatap.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | from textwrap import dedent 26 | from hpecp.datatap import Datatap 27 | from hpecp.cli import base 28 | 29 | 30 | class DatatapProxy(base.BaseProxy): 31 | """Proxy object to :py:attr:``.""" 32 | 33 | def __init__(self): 34 | """Create instance of proxy class with the client module name.""" 35 | super(DatatapProxy, self).new_instance("datatap", Datatap) 36 | 37 | def __dir__(self): 38 | """Return the CLI method names.""" 39 | return [ 40 | "create_hdfs_with_kerberos", 41 | "get", 42 | "list", 43 | "delete", 44 | # "examples", 45 | "wait_for_state", 46 | ] 47 | 48 | @base.intercept_exception 49 | def create_hdfs_with_kerberos( 50 | self, 51 | name, 52 | description="", 53 | path_from_endpoint="", 54 | kdc_data_host="", 55 | kdc_data_port="", 56 | realm="", 57 | client_principal="", 58 | browse_only=None, 59 | host="", 60 | keytab="", 61 | backup_host="", 62 | type="", 63 | port="", 64 | read_only=None, 65 | ): 66 | """TODO. 67 | 68 | Parameters 69 | ---------- 70 | name : [type] 71 | [description] 72 | description : [type] 73 | [description] 74 | path_from_endpoint : [type] 75 | [description] 76 | kdc_data_host : [type] 77 | [description] 78 | kdc_data_port : [type] 79 | [description] 80 | realm : [type] 81 | [description] 82 | client_principal : [type] 83 | [description] 84 | browse_only : [type] 85 | [description] 86 | host : [type] 87 | [description] 88 | keytab : [type] 89 | [description] 90 | service_id : [type] 91 | [description] 92 | backup_host : [type] 93 | [description] 94 | type : [type] 95 | [description] 96 | port : [type] 97 | [description] 98 | read_only : [type] 99 | [description] 100 | """ 101 | assert browse_only is not None and isinstance( 102 | browse_only, bool 103 | ), "'browse-only' parameter must be 'True' or 'False'" 104 | 105 | assert read_only is not None and isinstance( 106 | read_only, bool 107 | ), "'read-only' parameter must be 'True' or 'False'" 108 | 109 | base.get_client().datatap.create_hdfs_with_kerberos( 110 | name=name, 111 | description=description, 112 | path_from_endpoint=path_from_endpoint, 113 | kdc_data_host=kdc_data_host, 114 | kdc_data_port=kdc_data_port, 115 | realm=realm, 116 | client_principal=client_principal, 117 | browse_only=browse_only, 118 | host=host, 119 | keytab=keytab, 120 | backup_host=backup_host, 121 | type=type, 122 | port=port, 123 | read_only=read_only, 124 | ) 125 | 126 | def examples(self): 127 | """Show examples for working with roles.""" 128 | print( 129 | dedent( 130 | """\ 131 | # lookup datatap by name and retrieve ID 132 | $ PROFILE=tenant2 hpecp datatap list --query "[?_embedded.label.name=='int-mapr-generic'] | [0] | [_links.self.href]" --output text 133 | /api/v1/dataconn/11 134 | """ # noqa: E501 135 | ) 136 | ) 137 | -------------------------------------------------------------------------------- /hpecp/cli/gateway.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import sys 26 | from hpecp.gateway import Gateway, GatewayStatus 27 | from hpecp.cli import base 28 | 29 | 30 | class GatewayProxy(base.BaseProxy): 31 | """Proxy object to :py:attr:``.""" 32 | 33 | def __dir__(self): 34 | """Return the CLI method names.""" 35 | return [ 36 | "create_with_ssh_key", 37 | "delete", 38 | "get", 39 | "list", 40 | "states", 41 | "wait_for_state", 42 | ] 43 | 44 | def __init__(self): 45 | """Create instance of proxy class with the client module name.""" 46 | super(GatewayProxy, self).new_instance("gateway", Gateway) 47 | 48 | @base.intercept_exception 49 | def create_with_ssh_key( 50 | self, 51 | ip, 52 | proxy_node_hostname, 53 | ssh_key=None, 54 | ssh_key_file=None, 55 | ssh_passphrase=None, 56 | tags=[], 57 | ): 58 | """Create a Gateway using SSH key authentication. 59 | 60 | Parameters 61 | ---------- 62 | ip : string 63 | The IP address of the proxy host. Used for internal 64 | communication. 65 | proxy_node_hostname: string 66 | Clients will access cluster services will be accessed 67 | using this name. 68 | ssh_key: string 69 | The ssh key data as a string. Alternatively, use the 70 | ssh_key_file parameter. 71 | ssh_key_file: string 72 | The file path to the ssh key. Alternatively, use the 73 | ssh_key parameter. 74 | ssh_passphrase: string 75 | The passphrase 76 | tags: string 77 | Tags to add to the gateway, for example: 78 | "{ 'tag1': 'foo', 'tag2', 'bar' }". 79 | """ 80 | if ssh_key is None and ssh_key_file is None: 81 | print( 82 | "Either ssh_key or ssh_key_file must be provided", 83 | file=sys.stderr, 84 | ) 85 | sys.exit(1) 86 | 87 | if ssh_key is not None and ssh_key_file is not None: 88 | print( 89 | "Either ssh_key or ssh_key_file must be provided", 90 | file=sys.stderr, 91 | ) 92 | sys.exit(1) 93 | 94 | if ssh_key_file: 95 | with open(ssh_key_file) as f: 96 | ssh_key = f.read() 97 | 98 | gateway_id = base.get_client().gateway.create_with_ssh_key( 99 | ip=ip, 100 | proxy_node_hostname=proxy_node_hostname, 101 | ssh_key_data=ssh_key, 102 | ssh_passphrase=ssh_passphrase, 103 | tags=tags, 104 | ) 105 | print(gateway_id) 106 | 107 | def states( 108 | self, 109 | ): 110 | """Return a list of valid states.""" 111 | print([s.name for s in GatewayStatus]) 112 | -------------------------------------------------------------------------------- /hpecp/cli/httpclient.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import json 26 | import sys 27 | 28 | from hpecp.cli import base 29 | 30 | 31 | class HttpClientProxy(object): 32 | """Proxy object to :py:attr:``.""" 33 | 34 | def __dir__(self): 35 | """Return the CLI method names.""" 36 | return ["delete", "get", "post", "put"] 37 | 38 | @base.intercept_exception 39 | def get( 40 | self, 41 | url, 42 | ): 43 | """Make HTTP GET request. 44 | 45 | Examples 46 | -------- 47 | $ hpecp httpclient get /api/v1/workers 48 | > some output 49 | 50 | $ hpecp httpclient get /api/v2/tag | python3 -c \ 51 | 'import json,sys;obj=json.load(sys.stdin);[ print(t["_links"]["self"]["href"]) for t in obj["_embedded"]["tags"] if t["label"]["name"] == "Datafabric"]' 52 | /api/v2/tag/1 53 | """ # noqa: E501 54 | response = base.get_client()._request( 55 | url, 56 | http_method="get", 57 | description="CLI HTTP GET", 58 | ) 59 | 60 | try: 61 | response_info = json.dumps(response.json()) 62 | except Exception: 63 | response_info = response.text 64 | 65 | print(response_info, file=sys.stdout) 66 | 67 | @base.intercept_exception 68 | def delete( 69 | self, 70 | url, 71 | ): 72 | """Make HTTP DELETE request. 73 | 74 | Examples 75 | -------- 76 | $ hpecp httpclient delete /api/v1/workers/1 77 | """ 78 | base.get_client()._request( 79 | url, 80 | http_method="delete", 81 | description="CLI HTTP DELETE", 82 | ) 83 | 84 | @base.intercept_exception 85 | def post( 86 | self, 87 | url, 88 | json_file="", 89 | ): 90 | """Make HTTP POST request. 91 | 92 | Examples 93 | -------- 94 | $ cat > my.json <<-EOF 95 | { 96 | "external_identity_server": { 97 | "bind_pwd":"5ambaPwd@", 98 | "user_attribute":"sAMAccountName", 99 | "bind_type":"search_bind", 100 | "bind_dn":"cn=Administrator,CN=Users,DC=samdom,DC=example,DC=com", 101 | "host":"10.1.0.77", 102 | "security_protocol":"ldaps", 103 | "base_dn":"CN=Users,DC=samdom,DC=example,DC=com", 104 | "verify_peer": false, 105 | "type":"Active Directory", 106 | "port":636 107 | } 108 | } 109 | EOF 110 | 111 | hpecp httpclient post /api/v2/config/auth --json-file my.json 112 | """ 113 | with open( 114 | json_file, 115 | "r", 116 | ) as f: 117 | data = json.load(f) 118 | 119 | response = base.get_client()._request( 120 | url, 121 | http_method="post", 122 | data=data, 123 | description="CLI HTTP POST", 124 | ) 125 | print(response.text, file=sys.stdout) 126 | 127 | @base.intercept_exception 128 | def put( 129 | self, 130 | url, 131 | json_file="", 132 | ): 133 | """Make HTTP PUT request. 134 | 135 | Examples 136 | -------- 137 | $ hpecp httpclient put /api/v2/config/auth --json-file my.json 138 | """ # noqa: W293 139 | with open( 140 | json_file, 141 | "r", 142 | ) as f: 143 | data = json.load(f) 144 | 145 | response = base.get_client()._request( 146 | url, 147 | http_method="put", 148 | data=data, 149 | description="CLI HTTP PUT", 150 | ) 151 | print(response.text, file=sys.stdout) 152 | -------------------------------------------------------------------------------- /hpecp/cli/install.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import json 26 | import jmespath 27 | import sys 28 | import yaml 29 | from textwrap import dedent 30 | 31 | from hpecp.cli import base 32 | from hpecp.cli_utils import TextOutput 33 | 34 | 35 | class InstallProxy(object): 36 | """Proxy object to :py:attr:``.""" 37 | 38 | def __dir__(self): 39 | """Return the CLI method names.""" 40 | return ["examples", "get", "set_gateway_ssl"] 41 | 42 | @base.intercept_exception 43 | def get(self, output="yaml", query=None): 44 | """Get the system config. 45 | 46 | :param output: how to display the output '[yaml|json|json-pp]' 47 | """ 48 | if output not in ["yaml", "json", "json-pp", "text"]: 49 | print( 50 | ( 51 | "'output' parameter must be 'yaml', 'json', " 52 | "'json-pp' or 'text'." 53 | ), 54 | file=sys.stderr, 55 | ) 56 | sys.exit(1) 57 | 58 | if output == "yaml" and query is not None: 59 | print( 60 | "output=yaml is not supported with the query parameter.", 61 | file=sys.stderr, 62 | ) 63 | sys.exit(1) 64 | 65 | response = base.get_client().install.get() 66 | 67 | if output == "yaml": 68 | print( 69 | yaml.dump( 70 | yaml.load( 71 | json.dumps(response), 72 | Loader=yaml.FullLoader, 73 | ) 74 | ) 75 | ) 76 | else: 77 | if query is None: 78 | data = response 79 | else: 80 | data = jmespath.search(str(query), response) 81 | 82 | if output == "json-pp": 83 | print(json.dumps(data, indent=4, sort_keys=True)) 84 | elif output == "text": 85 | print(TextOutput.dump(data)) 86 | else: 87 | print(json.dumps(data)) 88 | 89 | def examples(self): 90 | """Show examples for working with roles.""" 91 | print( 92 | dedent( 93 | """\ 94 | 95 | """ # noqa: E501 96 | ) 97 | ) 98 | 99 | @base.intercept_exception 100 | def set_gateway_ssl( 101 | self, 102 | cert_file=None, 103 | cert_content=None, 104 | cert_file_name=None, 105 | key_file=None, 106 | key_content=None, 107 | key_file_name=None, 108 | ): 109 | """Set Gateway SSL. 110 | 111 | Parameters 112 | ---------- 113 | cert_file : [type] 114 | [description] 115 | cert_content : [type] 116 | [description] 117 | cert_file_name : [type] 118 | [description] 119 | key_file : [type] 120 | [description] 121 | key_content : [type] 122 | [description] 123 | key_file_name : [type] 124 | [description] 125 | """ 126 | assert ( 127 | cert_file is None 128 | and (cert_content is not None and cert_file_name is not None) 129 | ) or ( 130 | cert_file is not None 131 | and (cert_content is None and cert_file_name is None) 132 | ), ( 133 | "('cert-content' and 'cert-file-name') or 'cert-file' " 134 | "must be provided." 135 | ) 136 | 137 | assert ( 138 | key_file is None 139 | and (key_content is not None and key_file_name is not None) 140 | ) or ( 141 | key_file is not None 142 | and (key_content is None and key_file_name is None) 143 | ), ( 144 | "('key_content' and 'key_file-name') or 'key_file' " 145 | "must be provided." 146 | ) 147 | 148 | if cert_file: 149 | try: 150 | with open(cert_file, "r") as f: 151 | cert_content = ( 152 | f.read().replace("\n", "\n").replace("\t", "\t") 153 | ) 154 | cert_file_name = cert_file 155 | except OSError: 156 | print( 157 | "Could not open/read 'cert-file': {}".format(cert_file), 158 | file=sys.stderr, 159 | ) 160 | sys.exit(1) 161 | 162 | if key_file: 163 | try: 164 | with open(key_file, "r") as f: 165 | key_content = ( 166 | f.read().replace("\n", "\n").replace("\t", "\t") 167 | ) 168 | key_file_name = key_file 169 | except OSError: 170 | print( 171 | "Could not open/read 'key-file': {}".format(key_file), 172 | file=sys.stderr, 173 | ) 174 | sys.exit(1) 175 | 176 | base.get_client().install.set_gateway_ssl( 177 | cert_content, cert_file_name, key_content, key_file_name 178 | ) 179 | -------------------------------------------------------------------------------- /hpecp/cli/license.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import json 26 | import sys 27 | import yaml 28 | 29 | from hpecp.cli import base 30 | 31 | if sys.version_info[0] >= 3: 32 | unicode = str 33 | 34 | 35 | class LicenseProxy(object): 36 | """Proxy object to :py:attr:``.""" 37 | 38 | def __dir__(self): 39 | """Return the CLI method names.""" 40 | return ["delete", "delete_all", "list", "platform_id", "register"] 41 | 42 | @base.intercept_exception 43 | def platform_id( 44 | self, 45 | ): 46 | """Get the platform ID.""" 47 | print(base.get_client().license.platform_id()) 48 | 49 | def list( 50 | self, 51 | output="yaml", 52 | license_key_only=False, 53 | ): 54 | """Retrieve the list of licenses. 55 | 56 | :param output: how to display the output ['yaml'|'json'] 57 | """ 58 | response = base.get_client().license.list() 59 | if license_key_only: 60 | response = [ 61 | str(unicode(li["LicenseKey"])) for li in response["Licenses"] 62 | ] 63 | print("\n".join(response)) 64 | else: 65 | if output == "yaml": 66 | print( 67 | yaml.dump( 68 | yaml.load( 69 | json.dumps(response), 70 | Loader=yaml.FullLoader, 71 | ) 72 | ) 73 | ) 74 | else: 75 | print(json.dumps(response)) 76 | 77 | @base.intercept_exception 78 | def register( 79 | self, 80 | server_filename, 81 | ): 82 | """Register a license. 83 | 84 | :param server_filename: Filepath to the license on the server, e.g. 85 | '/srv/bluedata/license/LICENSE-1.txt' 86 | """ 87 | print( 88 | base.get_client().license.register(server_filename=server_filename) 89 | ) 90 | 91 | # TODO implement me! 92 | # def upload_with_ssh_key( 93 | # self, 94 | # server_filename, 95 | # ssh_key_file=None, 96 | # ssh_key_data=None, 97 | # license_file=None, 98 | # base64enc_license_data=None, 99 | # ): 100 | # """Not implemented yet. 101 | 102 | # Workaround: 103 | # ----------- 104 | # - scp your license to '/srv/bluedata/license/' on the controller 105 | # - run client.license.register(server_filename) to register 106 | # the license 107 | # """ 108 | # raise Exception( 109 | # "Not implemented yet! Workaround: scp your license to" 110 | # "'/srv/bluedata/license/'" 111 | # ) 112 | 113 | # TODO implement me! 114 | # def upload_with_ssh_pass( 115 | # self, 116 | # server_filename, 117 | # ssh_username, 118 | # ssh_password, 119 | # license_file=None, 120 | # base64enc_license_data=None, 121 | # ): 122 | # """Not implemented yet. 123 | 124 | # Workaround: 125 | # ----------- 126 | # - scp your license to '/srv/bluedata/license/' on the controller 127 | # - run client.license.register(server_filename) to register 128 | # the license 129 | # """ 130 | # raise Exception( 131 | # "Not implemented yet! Workaround: scp your license to" 132 | # "'/srv/bluedata/license/'" 133 | # ) 134 | 135 | @base.intercept_exception 136 | def delete( 137 | self, 138 | license_key, 139 | ): 140 | """Delete a license by LicenseKey. 141 | 142 | :param license_key: The license key, e.g. '1234 1234 ... 1234 143 | "SOMETEXT"' 144 | """ 145 | base.get_client().license.delete(license_key=license_key) 146 | 147 | @base.intercept_exception 148 | def delete_all( 149 | self, 150 | ): 151 | """Delete all licenses.""" 152 | response = base.get_client().license.list() 153 | all_license_keys = [ 154 | str(unicode(li["LicenseKey"])) for li in response["Licenses"] 155 | ] 156 | for licence_key in all_license_keys: 157 | base.get_client().license.delete(license_key=licence_key) 158 | -------------------------------------------------------------------------------- /hpecp/cli/lock.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | import json 26 | import sys 27 | import yaml 28 | 29 | from hpecp.cli import base 30 | 31 | 32 | class LockProxy(object): 33 | """Proxy object to :py:attr:``.""" 34 | 35 | def __dir__(self): 36 | """Return the CLI method names.""" 37 | return [ 38 | "create", 39 | "delete", 40 | "delete_all", 41 | "list", 42 | ] 43 | 44 | def list( 45 | self, 46 | output="yaml", 47 | ): 48 | """Get the system and user locks. 49 | 50 | :param output: how to display the output ['yaml'|'json'] 51 | """ 52 | if output not in ["yaml", "json"]: 53 | print( 54 | "'output' parameter must be 'yaml' or 'json'", file=sys.stderr 55 | ) 56 | sys.exit(1) 57 | 58 | response = base.get_client().lock.get() 59 | 60 | if output == "yaml": 61 | print( 62 | yaml.dump( 63 | yaml.load( 64 | json.dumps(response), 65 | Loader=yaml.FullLoader, 66 | ) 67 | ) 68 | ) 69 | else: 70 | print(json.dumps(response)) 71 | 72 | @base.intercept_exception 73 | def create(self, reason, timeout_secs=300): 74 | """Create a lock.""" 75 | response = base.get_client().lock.create(reason, timeout_secs) 76 | if response is False: 77 | print( 78 | "Unable to lock within '{}'".format(timeout_secs), 79 | file=sys.stderr, 80 | ) 81 | else: 82 | # reponse contains lock ID 83 | print(response, file=sys.stdout) 84 | 85 | @base.intercept_exception 86 | def delete( 87 | self, 88 | id, 89 | ): 90 | """Delete a user lock.""" 91 | base.get_client().lock.delete(id) 92 | 93 | @base.intercept_exception 94 | def delete_all( 95 | self, 96 | timeout_secs=300, 97 | ): 98 | """Delete all locks.""" 99 | success = base.get_client().lock.delete_all(timeout_secs=timeout_secs) 100 | if not success: 101 | print("Could not delete locks.", file=sys.stderr) 102 | sys.exit(1) 103 | -------------------------------------------------------------------------------- /hpecp/cli/role.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | from textwrap import dedent 26 | from hpecp.role import Role 27 | from hpecp.cli import base 28 | 29 | 30 | class RoleProxy(base.BaseProxy): 31 | """Proxy object to :py:attr:``.""" 32 | 33 | def __dir__(self): 34 | """Return the CLI method names.""" 35 | return ["delete", "examples", "get", "list"] 36 | 37 | def __init__(self): 38 | """Create instance of proxy class with the client module name.""" 39 | super(RoleProxy, self).new_instance("role", Role) 40 | 41 | def examples(self): 42 | """Show examples for working with roles.""" 43 | print( 44 | dedent( 45 | """\ 46 | 47 | # Retrieve the role ID for 'Admin' 48 | $ hpecp role list --query "[?label.name == 'Admin'][_links.self.href] | [0][0]" --output json | tr -d '"' 49 | /api/v1/role/2 50 | """ # noqa: E501 51 | ) 52 | ) 53 | -------------------------------------------------------------------------------- /hpecp/cli/tenant.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | from textwrap import dedent 26 | from hpecp.tenant import Tenant 27 | from hpecp.cli import base 28 | 29 | 30 | class TenantProxy(base.BaseProxy): 31 | """Proxy object to :py:attr:``.""" 32 | 33 | def __dir__(self): 34 | """Return the CLI method names.""" 35 | return [ 36 | "add_external_user_group", 37 | "assign_user_to_role", 38 | "create", 39 | "delete", 40 | "delete_external_user_group", 41 | "examples", 42 | "get", 43 | "get_external_user_groups", 44 | "k8skubeconfig", 45 | "list", 46 | # "status", # TODO: implement me! 47 | "users", 48 | "wait_for_status", 49 | ] 50 | 51 | def __init__(self): 52 | """Create instance of proxy class with the client module name.""" 53 | super(TenantProxy, self).new_instance("tenant", Tenant) 54 | 55 | @base.intercept_exception 56 | def create( 57 | self, 58 | name=None, 59 | description=None, 60 | tenant_type=None, 61 | k8s_cluster_id=None, 62 | is_namespace_owner=None, 63 | map_services_to_gateway=None, 64 | specified_namespace_name=None, 65 | adopt_existing_namespace=None, 66 | quota_memory=None, 67 | quota_persistent=None, 68 | quota_gpus=None, 69 | quota_cores=None, 70 | quota_disk=None, 71 | quota_tenant_storage=None, 72 | features=None, 73 | ): 74 | """Create a tenant. 75 | 76 | Parameters 77 | ---------- 78 | name : [type], optional 79 | [description], by default None 80 | description : [type], optional 81 | [description], by default None 82 | tenant_type : [type], optional 83 | [description], by default None 84 | k8s_cluster_id : [type], optional 85 | [description], by default None 86 | is_namespace_owner : [type], optional 87 | [description], by default None 88 | map_services_to_gateway : [type], optional 89 | [description], by default None 90 | specified_namespace_name : [type], optional 91 | [description], by default None 92 | adopt_existing_namespace : [type], optional 93 | [description], by default None 94 | """ 95 | tenant_id = base.get_client().tenant.create( 96 | name=name, 97 | description=description, 98 | tenant_type=tenant_type, 99 | k8s_cluster_id=k8s_cluster_id, 100 | is_namespace_owner=is_namespace_owner, 101 | map_services_to_gateway=map_services_to_gateway, 102 | specified_namespace_name=specified_namespace_name, 103 | adopt_existing_namespace=adopt_existing_namespace, 104 | quota_memory=quota_memory, 105 | quota_persistent=quota_persistent, 106 | quota_gpus=quota_gpus, 107 | quota_cores=quota_cores, 108 | quota_disk=quota_disk, 109 | quota_tenant_storage=quota_tenant_storage, 110 | features=features, 111 | ) 112 | print(tenant_id) 113 | 114 | def examples(self): 115 | """Show usage_examples of the list method.""" 116 | print( 117 | dedent( 118 | """\ 119 | # retrieve k8s tenants 120 | $ hpecp tenant list --query "[?tenant_type == 'k8s']" --output json-pp 121 | ... json output ... 122 | 123 | # retrieve tenant id of k8s tenant with name 'tenant1' 124 | $ hpecp tenant list --query "[?tenant_type == 'k8s' && label.name == 'tenant1'] | [0] | [_links.self.href]" --output text 125 | /api/v1/tenant/4 126 | 127 | """ # noqa: E501 128 | ) 129 | ) 130 | 131 | @base.intercept_exception 132 | def k8skubeconfig(self): 133 | """Retrieve the tenant kubeconfig. 134 | 135 | This requires the ContainerPlatformClient to be created with 136 | a 'tenant' parameter. 137 | 138 | Returns 139 | ------- 140 | str 141 | Tenant KubeConfig 142 | """ 143 | conf = base.get_client().tenant.k8skubeconfig() 144 | print(conf) 145 | 146 | @base.intercept_exception 147 | def users(self, id, output="table", columns="ALL", query={}): 148 | """Retrieve users assigned to tenant. 149 | 150 | Parameters 151 | ---------- 152 | id : str 153 | The tenant ID. 154 | """ 155 | list_instance = base.get_client().tenant.users(id=id) 156 | self.print_list( 157 | list_instance=list_instance, 158 | output=output, 159 | columns=columns, 160 | query=query, 161 | ) 162 | 163 | @base.intercept_exception 164 | def assign_user_to_role(self, tenant_id, user_id, role_id): 165 | """Assign user to role in tenant.""" 166 | base.get_client().tenant.assign_user_to_role( 167 | tenant_id=tenant_id, user_id=user_id, role_id=role_id 168 | ) 169 | 170 | @base.intercept_exception 171 | def get_external_user_groups(self, tenant_id): 172 | """Retrieve External User Groups.""" 173 | print( 174 | base.get_client().tenant.get_external_user_groups( 175 | tenant_id=tenant_id 176 | ) 177 | ) 178 | 179 | @base.intercept_exception 180 | def add_external_user_group(self, tenant_id, group, role_id): 181 | """Add External User Group.""" 182 | base.get_client().tenant.add_external_user_group( 183 | tenant_id=tenant_id, group=group, role_id=role_id 184 | ) 185 | 186 | @base.intercept_exception 187 | def delete_external_user_group(self, tenant_id, group): 188 | """Delete External User Group.""" 189 | base.get_client().tenant.delete_external_user_group( 190 | tenant_id=tenant_id, group=group 191 | ) 192 | -------------------------------------------------------------------------------- /hpecp/cli/user.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """HPE Container Platform CLI.""" 22 | 23 | from __future__ import print_function 24 | 25 | from textwrap import dedent 26 | from hpecp.user import User 27 | from hpecp.cli import base 28 | 29 | 30 | class UserProxy(base.BaseProxy): 31 | """Proxy object to :py:attr:``.""" 32 | 33 | def __dir__(self): 34 | """Return the CLI method names.""" 35 | return ["create", "get", "delete", "examples", "list"] 36 | 37 | def __init__(self): 38 | """Create instance of proxy class with the client module name.""" 39 | super(UserProxy, self).new_instance("user", User) 40 | 41 | @base.intercept_exception 42 | def create( 43 | self, 44 | name, 45 | password, 46 | description, 47 | is_external=False, 48 | ): 49 | """Create a User. 50 | 51 | :param name: the user name 52 | :param password: the password 53 | :param description: the user descripton 54 | 55 | """ 56 | user_id = base.get_client().user.create( 57 | name=name, 58 | password=password, 59 | description=description, 60 | is_external=is_external, 61 | ) 62 | print(user_id) 63 | 64 | def examples(self): 65 | """Show usage_examples of the list method.""" 66 | print( 67 | dedent( 68 | """\ 69 | 70 | hpecp user list --query '[?is_external]' --output json-pp 71 | """ # noqa: E501 72 | ) 73 | ) 74 | -------------------------------------------------------------------------------- /hpecp/cli_utils.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """CLI Utilities.""" 22 | 23 | from collections import OrderedDict 24 | from io import StringIO 25 | 26 | import six 27 | from six import string_types 28 | 29 | # This class has been adapted from knack. 30 | # See https://github.com/microsoft/knack/blob/master/LICENSE 31 | 32 | 33 | class TextOutput(object): 34 | """Text output class.""" 35 | 36 | @staticmethod 37 | def _dump_obj(data, stream): 38 | if isinstance(data, list): 39 | stream.write(str(len(data))) 40 | elif isinstance(data, dict): 41 | # We need to print something to avoid mismatching 42 | # number of columns if the value is None for some instances 43 | # and a dictionary value in other... 44 | stream.write("") 45 | else: 46 | to_write = data if isinstance(data, string_types) else str(data) 47 | stream.write(to_write) 48 | 49 | @staticmethod 50 | def _dump_row(data, stream): 51 | separator = "" 52 | if isinstance(data, (dict, list)): 53 | if isinstance(data, OrderedDict): 54 | values = data.values() 55 | elif isinstance(data, dict): 56 | values = [value for _, value in sorted(data.items())] 57 | else: 58 | values = data 59 | 60 | for value in values: 61 | stream.write(separator) 62 | TextOutput._dump_obj(value, stream) 63 | separator = "\t" 64 | elif isinstance(data, list): 65 | for value in data: 66 | stream.write(separator) 67 | TextOutput._dump_obj(value, stream) 68 | separator = "\t" 69 | elif isinstance(data, bool): 70 | TextOutput._dump_obj(str(data).lower(), stream) 71 | else: 72 | TextOutput._dump_obj(data, stream) 73 | stream.write("\n") 74 | 75 | @staticmethod 76 | def dump(data): 77 | """Dump the python object as text.""" # noqa: D202 78 | 79 | if data is None: 80 | return str("") 81 | 82 | class MyStringIO(StringIO): 83 | def write(self, b): 84 | if six.PY2: 85 | val = unicode(b) # noqa: F821 86 | else: 87 | val = b 88 | super(MyStringIO, self).write(val) 89 | 90 | io = MyStringIO() 91 | for item in data: 92 | if item is not None: 93 | TextOutput._dump_row(item, io) 94 | 95 | result = io.getvalue() 96 | io.close() 97 | return str(result) 98 | -------------------------------------------------------------------------------- /hpecp/config.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import absolute_import 22 | 23 | 24 | class ConfigController: 25 | def __init__(self, client): 26 | self.client = client 27 | 28 | def get(self): 29 | response = self.client._request( 30 | url="/api/v1/config", 31 | http_method="get", 32 | description="config/get", 33 | ) 34 | return response.json() 35 | 36 | def auth(self, data): 37 | """ 38 | Example:: 39 | data = { 40 | "external_identity_server": { 41 | "bind_pwd":"5ambaPwd@", 42 | "user_attribute":"sAMAccountName", 43 | "bind_type":"search_bind", 44 | "bind_dn":"cn=Administrator,CN=Users,DC=samdom,DC=example,DC=com", 45 | "host":"10.1.0.77", 46 | "security_protocol":"ldaps", 47 | "base_dn":"CN=Users,DC=samdom,DC=example,DC=com", 48 | "verify_peer": False, 49 | "type":"Active Directory", 50 | "port":636 51 | } 52 | } 53 | """ 54 | self.client._request( 55 | url="/api/v2/config/auth", 56 | http_method="post", 57 | data=data, 58 | description="config/auth", 59 | ) 60 | -------------------------------------------------------------------------------- /hpecp/datatap.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """Module for working with datatap.""" 22 | 23 | from .base_resource import AbstractResource, AbstractResourceController 24 | 25 | 26 | class Datatap(AbstractResource): 27 | """Datatap Image item.""" 28 | 29 | # All of the fields of Catalog objects as returned by the HPE Container 30 | # Platform API. 31 | # TODO: Verify this with the specification 32 | all_fields = ( 33 | "id", 34 | "name", 35 | "description", 36 | "type", 37 | "status", 38 | ) 39 | 40 | default_display_fields = [ 41 | "id", 42 | "name", 43 | "description", 44 | "type", 45 | "status", 46 | ] 47 | 48 | # These fields are displayed by default, e.g. in tabulate() 49 | # TODO: Verify this with the specification 50 | # TODO: Pick a smaller subset, again based on the API response 51 | default_display_fields = all_fields 52 | 53 | @property 54 | def name(self): 55 | """@Field: from json['_embedded']['label']['name'].""" 56 | try: 57 | return self.json["_embedded"]["label"]["name"] 58 | except KeyError: 59 | return "" 60 | 61 | @property 62 | def description(self): 63 | """@Field: from json['_embedded']['label']['description'].""" 64 | try: 65 | return self.json["_embedded"]["label"]["description"] 66 | except KeyError: 67 | return "" 68 | 69 | @property 70 | def type(self): 71 | """@Field: from json['_embedded']['endpoint']['type'].""" 72 | try: 73 | return self.json["_embedded"]["endpoint"]["type"] 74 | except KeyError: 75 | return "" 76 | 77 | @property 78 | def self_href(self): 79 | """@Field: from json['_links']['self']['href'].""" 80 | try: 81 | return self.json["_links"]["self"]["href"] 82 | except KeyError: 83 | return "" 84 | 85 | @property 86 | def status(self): 87 | """@Field: from json['_embedded']['status'].""" 88 | try: 89 | return self.json["_embedded"]["status"] 90 | except KeyError: 91 | return "" 92 | 93 | 94 | class DatatapController(AbstractResourceController): 95 | """Class that users will interact with to work with datataps. 96 | 97 | An instance of this class is available in the 98 | `client.ContainerPlatformClient` with the attribute name 99 | :py:attr:`datatap <.client.ContainerPlatformClient.catalog>`. The methods 100 | of this class can be invoked using `client.datatap.method()`. See the 101 | example below: 102 | 103 | Examples 104 | -------- 105 | >>> client = ContainerPlatformClient(...).create_session() 106 | >>> client.datatap.list() 107 | """ 108 | 109 | base_resource_path = "/api/v1/dataconn" 110 | 111 | resource_list_path = "data_connectors" 112 | 113 | resource_class = Datatap 114 | 115 | def create_hdfs_with_kerberos( 116 | self, 117 | name, 118 | description, 119 | path_from_endpoint, 120 | kdc_data_host, 121 | kdc_data_port, 122 | realm, 123 | client_principal, 124 | browse_only, 125 | host, 126 | keytab, 127 | backup_host, 128 | type, 129 | port, 130 | read_only, 131 | ): 132 | """TODO. 133 | 134 | Parameters 135 | ---------- 136 | name : [type] 137 | [description] 138 | description : [type] 139 | [description] 140 | path_from_endpoint : [type] 141 | [description] 142 | kdc_data_host : [type] 143 | [description] 144 | kdc_data_port : [type] 145 | [description] 146 | realm : [type] 147 | [description] 148 | client_principal : [type] 149 | [description] 150 | browse_only : [type] 151 | [description] 152 | host : [type] 153 | [description] 154 | keytab : [type] 155 | [description] 156 | backup_host : [type] 157 | [description] 158 | type : [type] 159 | [description] 160 | port : [type] 161 | [description] 162 | read_only : [type] 163 | [description] 164 | """ 165 | _data = { 166 | "bdfs_root": {}, 167 | "endpoint": { 168 | "kdc_data": [ 169 | { 170 | "host": kdc_data_host, 171 | } 172 | ], 173 | "realm": realm, 174 | "client_principal": client_principal, 175 | "browse_only": browse_only, 176 | "host": host, 177 | "keytab": keytab, 178 | "service_id": "hdfs", 179 | "backup_host": backup_host, 180 | "type": type, 181 | "port": str(port), 182 | }, 183 | "flags": {"read_only": read_only}, 184 | "label": {"name": name, "description": description}, 185 | } 186 | 187 | if path_from_endpoint != "": 188 | _data["bdfs_root"]["path_from_endpoint"] = path_from_endpoint 189 | 190 | if kdc_data_port != "": 191 | _data["endpoint"]["kdc_data"]["kdc_data_port"] = kdc_data_port 192 | 193 | self.client._request( 194 | url=DatatapController.base_resource_path, 195 | http_method="post", 196 | description="datatap/create", 197 | data=_data, 198 | ) 199 | -------------------------------------------------------------------------------- /hpecp/exceptions.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | class ContainerPlatformClientException(Exception): 23 | def __init__(self, message, *args): 24 | self.message = message 25 | super(ContainerPlatformClientException, self).__init__(message, *args) 26 | 27 | 28 | class APIException(Exception): 29 | def __init__( 30 | self, message, request_method, request_url, request_data=None, *args 31 | ): 32 | self.message = message 33 | self.request_method = request_method 34 | self.request_url = request_url 35 | self.request_data = request_data 36 | super(APIException, self).__init__( 37 | message, request_method, request_url, request_data, *args 38 | ) 39 | 40 | 41 | class APIUnknownException(APIException): 42 | pass 43 | 44 | 45 | class APIItemNotFoundException(APIException): 46 | def __init__( 47 | self, message, request_method, request_url, request_data=None, *args 48 | ): 49 | self.message = message 50 | self.request_method = request_method 51 | self.request_url = request_url 52 | self.request_data = request_data 53 | super(APIItemNotFoundException, self).__init__( 54 | message, request_method, request_url, request_data, *args 55 | ) 56 | 57 | 58 | class APIForbiddenException(APIException): 59 | def __init__( 60 | self, message, request_method, request_url, request_data=None, *args 61 | ): 62 | self.message = message 63 | self.request_method = request_method 64 | self.request_url = request_url 65 | self.request_data = request_data 66 | super(APIForbiddenException, self).__init__( 67 | message, request_method, request_url, request_data, *args 68 | ) 69 | 70 | 71 | class APIItemConflictException(APIException): 72 | def __init__( 73 | self, message, request_method, request_url, request_data=None, *args 74 | ): 75 | self.message = message 76 | self.request_method = request_method 77 | self.request_url = request_url 78 | self.request_data = request_data 79 | super(APIItemConflictException, self).__init__( 80 | message, request_method, request_url, request_data, *args 81 | ) 82 | -------------------------------------------------------------------------------- /hpecp/install.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | """Python library code for working with install API.""" 22 | 23 | from __future__ import absolute_import 24 | 25 | 26 | class InstallController: 27 | """Controller for working with the install API.""" 28 | 29 | def __init__(self, client): 30 | self.client = client 31 | 32 | def get(self): 33 | """Get Install information. 34 | 35 | Returns 36 | ------- 37 | [type] 38 | [description] 39 | """ 40 | response = self.client._request( 41 | url="/api/v1/install", 42 | http_method="get", 43 | description="install/get", 44 | ) 45 | return response.json() 46 | 47 | def set_gateway_ssl( 48 | self, cert_content, cert_file_name, key_content, key_file_name 49 | ): 50 | """Set Gateway SSL.""" 51 | _data = { 52 | "gateway_ssl_cert_info": { 53 | "cert_file": { 54 | "content": cert_content, 55 | "file_name": cert_file_name, 56 | }, 57 | "key_file": { 58 | "content": key_content, 59 | "file_name": key_file_name, 60 | }, 61 | } 62 | } 63 | 64 | self.client._request( 65 | url="/api/v1/install?install_reconfig", 66 | http_method="put", 67 | data=_data, 68 | description="install/set_gateway_ssl", 69 | ) 70 | -------------------------------------------------------------------------------- /hpecp/k8s_worker.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import absolute_import 22 | 23 | from enum import Enum 24 | 25 | from requests.structures import CaseInsensitiveDict 26 | 27 | from .base_resource import AbstractResource, AbstractWaitableResourceController 28 | 29 | try: 30 | basestring 31 | except NameError: 32 | basestring = str 33 | 34 | 35 | class WorkerK8sStatus(Enum): 36 | bundle = 1 37 | installing = 2 38 | installed = 3 39 | ready = 4 40 | unlicensed = 5 41 | configuring = 6 42 | configured = 7 43 | error = 8 44 | sysinfo = 9 45 | unconfiguring = 10 46 | deleting = 11 47 | storage_pending = 12 48 | storage_configuring = 13 49 | storage_error = 14 50 | 51 | 52 | class WorkerK8s(AbstractResource): 53 | 54 | all_fields = [ 55 | "id", 56 | "status", 57 | "hostname", 58 | "ipaddr", 59 | "href", 60 | "_links", 61 | ] 62 | """All of the fields of a K8s Cluster objects that are returned by the HPE 63 | Container Platform API""" 64 | 65 | default_display_fields = [ 66 | "id", 67 | "status", 68 | "hostname", 69 | "ipaddr", 70 | ] 71 | 72 | @property 73 | def worker_id(self): 74 | return int(self.json["_links"]["self"]["href"].split("/")[-1]) 75 | 76 | @property 77 | def status(self): 78 | return self.json["status"] 79 | 80 | @property 81 | def hostname(self): 82 | return self.json["hostname"] 83 | 84 | @property 85 | def ipaddr(self): 86 | return self.json["ipaddr"] 87 | 88 | @property 89 | def href(self): 90 | return self.json["_links"]["self"]["href"] 91 | 92 | 93 | class K8sWorkerController(AbstractWaitableResourceController): 94 | 95 | base_resource_path = "/api/v2/worker/k8shost" 96 | 97 | resource_list_path = "k8shosts" 98 | 99 | resource_class = WorkerK8s 100 | 101 | status_class = WorkerK8sStatus 102 | 103 | status_fieldname = "status" 104 | 105 | # TODO implement me! 106 | # def create_with_ssh_password(self, username, password): 107 | # """Not Implemented yet""" 108 | # raise NotImplementedError() 109 | 110 | def create_with_ssh_key( 111 | self, ip, ssh_key_data, ssh_passphrase=None, tags=[] 112 | ): 113 | """Create a gateway instance using SSH key credentials to access the host. 114 | 115 | Parameters 116 | ---------- 117 | ip: str 118 | The IP address of the proxy host. Used for internal 119 | communication. 120 | ssh_key_data: str 121 | The ssh key data as a string. 122 | ssh_passphrase: str 123 | The ssh passphrase 124 | tags: list 125 | Tags to use, e.g. "{ 'tag1': 'foo', 'tag2', 'bar' }". 126 | 127 | Returns 128 | ------- 129 | string 130 | Worker ID 131 | """ 132 | 133 | assert isinstance( 134 | ip, basestring 135 | ), "'ip' must be provided and must be a string" 136 | assert isinstance( 137 | ssh_key_data, basestring 138 | ), "'ssh_key_data' must be provided and must be a string" 139 | 140 | data = { 141 | "ipaddr": ip, 142 | "credentials": { 143 | "type": "ssh_key_access", 144 | "ssh_key_data": ssh_key_data, 145 | }, 146 | "tags": tags, 147 | } 148 | 149 | if ssh_passphrase is not None: 150 | data["credentials"]["ssh_key_passphrase"] = ssh_passphrase 151 | 152 | response = self.client._request( 153 | url="/api/v2/worker/k8shost/", 154 | http_method="post", 155 | data=data, 156 | description="K8sWorkerController/create_with_ssh_key", 157 | ) 158 | return CaseInsensitiveDict(response.headers)["location"] 159 | 160 | def get(self, id, params=None, setup_log=False): 161 | 162 | if params is None: 163 | params = {} 164 | 165 | if setup_log is True: 166 | params["setup_log"] = "true" 167 | 168 | return super(K8sWorkerController, self).get(id, params) 169 | 170 | def set_storage(self, worker_id, ephemeral_disks=[], persistent_disks=[]): 171 | """Set storage for a k8s worker. 172 | 173 | Parameters 174 | ---------- 175 | worker_id : str 176 | The k8s worker ID, format - '/api/v2/worker/k8shost/[0-9]+' 177 | ephemeral_disks : list 178 | List of ephemeral disks. Mandatory parameter, by default [] 179 | persistent_disks : list, optional 180 | List of persistent disks, by default [] 181 | 182 | Raises 183 | ------ 184 | APIItemNotFoundException 185 | APIItemConflictException 186 | APIException 187 | AssertionError 188 | """ 189 | # Make sure that the worker exists 190 | self.get(worker_id) 191 | 192 | assert isinstance( 193 | ephemeral_disks, list 194 | ), "'ephemeral_disks' must be provided and and must be a list" 195 | 196 | assert ( 197 | len(ephemeral_disks) > 0 198 | ), "'ephemeral_disks' must contain at least one disk" 199 | 200 | assert isinstance( 201 | persistent_disks, list 202 | ), "'persistent_disks' must be a list" 203 | 204 | # Prepare the payload 205 | data = { 206 | "op_spec": { 207 | "ephemeral_disks": ephemeral_disks, 208 | "persistent_disks": persistent_disks, 209 | }, 210 | "op": "storage", 211 | } 212 | 213 | # Make the request 214 | self.client._request( 215 | url=worker_id, 216 | http_method="post", 217 | data=data, 218 | description="worker/set_storage", 219 | ) 220 | -------------------------------------------------------------------------------- /hpecp/license.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import absolute_import 22 | 23 | import urllib 24 | 25 | from requests.structures import CaseInsensitiveDict 26 | 27 | 28 | class LicenseController: 29 | def __init__(self, client): 30 | self.client = client 31 | 32 | def platform_id(self): 33 | """Retrieve the Platform ID""" 34 | response = self.client._request( 35 | url="/api/v1/license", 36 | http_method="get", 37 | description="license/get_platform_id", 38 | ) 39 | return response.json()["uuid"] 40 | 41 | def list(self): 42 | """Retrieve the list of licenses""" 43 | response = self.client._request( 44 | url="/api/v2/hpelicense", 45 | http_method="get", 46 | description="license/get_license", 47 | ) 48 | return response.json() 49 | 50 | def upload_with_ssh_key( 51 | self, 52 | server_filename, 53 | ssh_key_file=None, 54 | ssh_key_data=None, 55 | base64enc_license="", 56 | ): 57 | """Not implemented yet! 58 | 59 | Workaround: 60 | - scp your license to '/srv/bluedata/license/' on the controller 61 | - run client.license.register(server_filename) to register the license 62 | """ 63 | raise Exception( 64 | "Not implemented yet! Workaround: scp your license to" 65 | " '/srv/bluedata/license/'" 66 | ) 67 | 68 | def upload_with_ssh_pass( 69 | self, server_filename, ssh_username, ssh_password, base64enc_license="" 70 | ): 71 | """Not implemented yet! 72 | 73 | Workaround: 74 | - scp your license to '/srv/bluedata/license/' on the controller 75 | - run client.license.register(server_filename) to register the license 76 | """ 77 | raise Exception( 78 | "Not implemented yet! Workaround: scp your license to" 79 | "'/srv/bluedata/license/'" 80 | ) 81 | 82 | def register(self, server_filename): 83 | """Register a license. The license must have previously been uploaded 84 | to '/srv/bluedata/license/' on the controller. 85 | 86 | Parameters 87 | ---------- 88 | server_filename: str 89 | Filepath to the license on the server, e.g. 90 | '/srv/bluedata/license/LICENSE-1.txt' 91 | 92 | Raises 93 | ------ 94 | APIException 95 | """ 96 | data = {"hpelicense_file": server_filename} 97 | response = self.client._request( 98 | url="/api/v2/hpelicense", 99 | http_method="post", 100 | data=data, 101 | description="license/register", 102 | ) 103 | return CaseInsensitiveDict(response.headers)["Location"] 104 | 105 | def delete(self, license_key): 106 | """Delete a license by LicenseKey. 107 | 108 | Parameters 109 | ---------- 110 | license_key: str 111 | The license key, e.g. '1234 1234 ... 1234 "SOMETEXT"' 112 | 113 | Raises 114 | ------ 115 | APIException 116 | """ 117 | 118 | try: 119 | lic = urllib.parse.quote(license_key) # python 2 120 | except Exception: 121 | lic = urllib.pathname2url(license_key) # python 3 122 | 123 | return self.client._request( 124 | url="/api/v2/hpelicense/{}/".format(lic), 125 | http_method="delete", 126 | description="license/delete", 127 | ) 128 | -------------------------------------------------------------------------------- /hpecp/lock.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import absolute_import 22 | 23 | import re 24 | 25 | import polling 26 | from requests.structures import CaseInsensitiveDict 27 | 28 | from .logger import Logger 29 | 30 | _log = Logger.get_logger() 31 | 32 | try: 33 | basestring 34 | except NameError: 35 | basestring = str 36 | 37 | 38 | class LockController: 39 | def __init__(self, client): 40 | self.client = client 41 | 42 | def get(self): 43 | """Retrieve the locks""" 44 | return self.client._request( 45 | url="/api/v1/lock", http_method="get", description="lock/get_locks" 46 | ).json() 47 | 48 | def list(self): 49 | """Retrieve the locks""" 50 | return self.get() 51 | 52 | def create(self, reason=None, timeout_secs=300): 53 | """Create a new lock. 54 | 55 | Arguments 56 | --------- 57 | reason: str 58 | Provide a reason for the lock. 59 | timeout_secs: int 60 | Time to wait for lock to be successful 61 | 62 | Raises 63 | ------ 64 | APIException 65 | """ 66 | data = {"reason": reason} 67 | response = self.client._request( 68 | url="/api/v1/lock", 69 | http_method="post", 70 | data=data, 71 | description="lock/set_lock", 72 | ) 73 | lock_id = CaseInsensitiveDict(response.headers)["Location"] 74 | 75 | if timeout_secs == 0: 76 | return lock_id 77 | else: 78 | try: 79 | 80 | def poll(): 81 | locked = self.get()["locked"] 82 | quiesced = self.get()["quiesced"] 83 | _log.debug( 84 | "In poll loop - locked={} quiesced={}".format( 85 | locked, quiesced 86 | ) 87 | ) 88 | return locked and quiesced 89 | 90 | polling.poll( 91 | lambda: poll(), 92 | step=10, 93 | poll_forever=False, 94 | timeout=timeout_secs, 95 | ) 96 | return lock_id 97 | except polling.TimeoutException: 98 | return False 99 | 100 | def delete(self, lock_id): 101 | """Delete a lock. 102 | 103 | Parameters 104 | ---------- 105 | lock_id: str 106 | The lock id as retrieved with `get()` Format: 107 | '/api/v1/lock/[0-9]+' 108 | 109 | Raises 110 | ------ 111 | APIException 112 | """ 113 | 114 | assert isinstance( 115 | lock_id, basestring 116 | ), "'lock_id' must be provided and must be a string" 117 | assert re.match( 118 | r"\/api\/v1\/lock\/[0-9]+", lock_id 119 | ), "'lock_id' must have format '/api/v1/lock/[0-9]+'" 120 | 121 | return self.client._request( 122 | url=lock_id, http_method="delete", description="lock/delete_lock" 123 | ) 124 | 125 | def delete_all(self, timeout_secs=300): 126 | """Delete all locks. 127 | 128 | Parameters 129 | ---------- 130 | timeout_secs: int 131 | How long to wait for internal locks (note these need to be 132 | cleared before external locks can be deleted) 133 | 134 | Raises 135 | ------ 136 | APIException 137 | """ 138 | 139 | try: 140 | polling.poll( 141 | lambda: len(self.get()["_embedded"]["internal_locks"]) == 0, 142 | step=10, 143 | poll_forever=False, 144 | timeout=timeout_secs, 145 | ) 146 | except polling.TimeoutException: 147 | return False 148 | except Exception as e: 149 | self.client.log.error(e) 150 | return False 151 | 152 | if len(self.get()["_embedded"]["external_locks"]) > 0: 153 | for lock in self.get()["_embedded"]["external_locks"]: 154 | lock_id = lock["_links"]["self"]["href"] 155 | self.delete(lock_id) 156 | 157 | return True 158 | -------------------------------------------------------------------------------- /hpecp/logger.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | import logging 22 | import logging.config 23 | import os 24 | 25 | 26 | class Logger(object): 27 | 28 | logger = None 29 | 30 | @classmethod 31 | def get_logger(cls): 32 | 33 | if "HPECP_LOG_CONFIG_FILE" in os.environ: 34 | logging.config.fileConfig(os.getenv("HPECP_LOG_CONFIG_FILE")) 35 | Logger.logger = logging.getLogger("HPECP_CLI") 36 | else: 37 | format = ( 38 | "%(asctime)s - %(filename)s " 39 | "- %(name)s - %(levelname)s - %(message)s" 40 | ) 41 | logging.basicConfig(format=format) 42 | Logger.logger = logging.getLogger("HPECP_CLI") 43 | Logger.logger.setLevel(os.getenv("LOG_LEVEL", logging.INFO)) 44 | 45 | return Logger.logger 46 | -------------------------------------------------------------------------------- /hpecp/role.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import absolute_import 22 | 23 | import re 24 | 25 | from .base_resource import AbstractResource, AbstractResourceController 26 | 27 | try: 28 | basestring 29 | except NameError: 30 | basestring = str 31 | 32 | 33 | class Role(AbstractResource): 34 | """Create an instance of Role from json data returned from the HPE 35 | Container Platform API. 36 | 37 | Users of this library are not expected to create an instance of this class. 38 | 39 | Parameters: 40 | json : str 41 | The json returned by the API representing a Gateway. 42 | 43 | Returns: 44 | Gateway: 45 | An instance of Gateway 46 | """ 47 | 48 | all_fields = [ 49 | "id", 50 | "name", 51 | "description", 52 | ] 53 | """All of the fields of Role objects as returned by the HPE Container 54 | Platform API""" 55 | 56 | default_display_fields = [ 57 | "id", 58 | "name", 59 | "description", 60 | ] 61 | 62 | @property 63 | def id(self): 64 | """@Field: from json['_links']['self']['href'] - id format: 65 | '/api/v1/role/[0-9]+'""" 66 | return self.json["_links"]["self"]["href"] 67 | 68 | @property 69 | def name(self): 70 | """@Field: from json['label']['name']""" 71 | return self.json["label"]["name"] 72 | 73 | @property 74 | def description(self): 75 | """@Field: from json['label']['description']""" 76 | return self.json["label"]["description"] 77 | 78 | 79 | class RoleController(AbstractResourceController): 80 | """This is the main class that users will interact with to work with roles. 81 | 82 | An instance of this class is available in the 83 | client.ContainerPlatformClient with the attribute name 84 | :py:attr:`role <.client.ContainerPlatformClient.role>`. The methods of 85 | this class can be 86 | invoked using `client.role.method()`. See the example below: 87 | 88 | Example:: 89 | 90 | client = ContainerPlatformClient(...).create_session() 91 | client.role.get() 92 | 93 | """ 94 | 95 | base_resource_path = "/api/v1/role/" 96 | resource_class = Role 97 | resource_list_path = "roles" 98 | -------------------------------------------------------------------------------- /pre_push_verifications.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ -d /home/theia/ ]]; 6 | then 7 | # black and isort have been installed in the 3.8.x pyenv 8 | eval "$(pyenv init -)" 9 | pyenv shell $(pyenv versions --bare | grep 3.8) 10 | fi 11 | 12 | isort tests/*.py hpecp/**.py bin/*.py 13 | black bin/ tests/ hpecp/ 14 | 15 | #flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 16 | flake8 --docstring-convention numpy bin/ hpecp/ 17 | flake8 --ignore=D,E501 tests/ # verify tests, but not for documentation 18 | 19 | if [[ -d /home/theia/ ]]; 20 | then 21 | # ensure pyenvs are available to tox 22 | pyenv shell $(pyenv versions --bare) 23 | fi 24 | 25 | tox -- tests/ 26 | 27 | # coverage causes some tests to fail on PY3 so test it (issues 93) 28 | #coverage3 erase && coverage3 run --source hpecp,bin setup.py test && coverage3 report -m -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 79 3 | 4 | [tool.semantic_release] 5 | version_variable = [ 6 | 'hpecp/__init__.py:__version__', 7 | #'docs/conf.py:version', 8 | ] 9 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | future 2 | requests 3 | tabulate 4 | six 5 | enum34; python_version == "2.7" 6 | configparser; python_version == "2.7" 7 | polling 8 | pyyaml>=5.1 9 | fire 10 | jmespath 11 | jinja2 12 | wrapt -------------------------------------------------------------------------------- /run_ide.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | IMG=hpecp/hpecp-ide:latest 4 | 5 | if [[ "$(docker images -q $IMG 2> /dev/null)" == "" ]]; then 6 | ./build_ide.sh 7 | fi 8 | 9 | echo 10 | 11 | git_vars=1 12 | if [[ -z $GIT_USER ]]; then 13 | echo "GIT_USER variable not found" 14 | git_vars=0 15 | fi 16 | 17 | if [[ -z $GIT_PASS ]]; then 18 | echo "GIT_PASS variable not found" 19 | git_vars=0 20 | fi 21 | 22 | if [[ -z $GIT_AUTHOR_NAME ]]; then 23 | echo "GIT_AUTHOR_NAME variable not found" 24 | git_vars=0 25 | fi 26 | 27 | if [[ -z $GIT_COMMITTER_NAME ]]; then 28 | echo "GIT_COMMITTER_NAME variable not found" 29 | git_vars=0 30 | fi 31 | 32 | if [[ -z $GIT_AUTHOR_EMAIL ]]; then 33 | echo "GIT_AUTHOR_EMAIL variable not found" 34 | git_vars=0 35 | fi 36 | 37 | if [[ -z $GIT_COMMITTER_EMAIL ]]; then 38 | echo "GIT_COMMITER_EMAIL variable not found" 39 | git_vars=0 40 | fi 41 | 42 | if [[ $git_vars == 0 ]]; then 43 | echo 44 | echo "WARNING:" 45 | echo "One or more git variables were not set." 46 | echo "You will not be able to push/pull to github from inside theia." 47 | echo 48 | echo "TIP:" 49 | echo "you can set these variables in .bashrc or .bash_profile, e.g." 50 | echo ------------------------------------- 51 | echo export GIT_USER=your_git_username 52 | echo export GIT_PASS=your_git_password 53 | echo export GIT_AUTHOR_NAME="Your name" 54 | echo export GIT_COMMITTER_NAME="Your name" 55 | echo export GIT_AUTHOR_EMAIL=your@email 56 | echo export GIT_COMMITTER_EMAIL=your@email 57 | echo ------------------------------------- 58 | echo 59 | 60 | while true; do 61 | read -p "Do you want to continue without git configured in Theia?" yn 62 | case $yn in 63 | [Yy]* ) break;; 64 | [Nn]* ) exit;; 65 | * ) echo "Please answer yes or no.";; 66 | esac 67 | done 68 | fi 69 | 70 | if [[ "$OSTYPE" == "linux-gnu"* ]]; then 71 | UID_GID_OPTION="-u $(id -u ${USER}):$(id -g ${USER})" 72 | fi 73 | 74 | docker run -it --init \ 75 | -p 3000:3000 \ 76 | ${UID_GID_OPTION} \ 77 | -v "$(pwd):/home/project:cached" \ 78 | -e GIT_USER="$GIT_USER" \ 79 | -e GIT_PASS="$GIT_PASS" \ 80 | -e GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \ 81 | -e GIT_COMMITTER_NAME="$GIT_COMMITTER_NAME" \ 82 | -e GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \ 83 | -e GIT_COMMITTER_EMAIL="$GIT_COMMITTER_EMAIL" \ 84 | -e GIT_ASKPASS=/home/project/git_env_password.sh \ 85 | $IMG 86 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [flake8] 5 | per-file-ignores = hpecp/__init__.py:F401 6 | # Temporarily disable docstring violations 7 | hpecp/catalog.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 8 | hpecp/config.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 9 | hpecp/gateway.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 10 | hpecp/logger.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 11 | hpecp/lock.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 12 | hpecp/k8s_cluster.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 13 | hpecp/k8s_worker.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 14 | hpecp/epic_worker.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 15 | hpecp/license.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 16 | hpecp/exceptions.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 17 | hpecp/user.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 18 | hpecp/tenant.py:D101,D102,D100,D107,D105,D209,D400,D202,D205,D401,D200,D412 19 | exclude = hpecp/role.py 20 | 21 | [pycodestyle] 22 | max-line-length = 79 23 | 24 | [isort] 25 | multi_line_output=3 26 | include_trailing_comma=True 27 | force_grid_wrap=0 28 | use_parentheses=True 29 | line_length=79 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from setuptools import setup 22 | import codecs 23 | import os 24 | import shutil 25 | 26 | if "TRAVIS_BUILD_DIR" in os.environ: 27 | REQ_PATH = os.getenv("TRAVIS_BUILD_DIR") 28 | elif "TOX_BUILD_DIR" in os.environ: 29 | REQ_PATH = os.getenv("TOX_BUILD_DIR") 30 | else: 31 | REQ_PATH = "." 32 | 33 | with open(REQ_PATH + "/requirements.txt") as f: 34 | requirements = f.read().splitlines() 35 | 36 | shutil.copyfile(REQ_PATH + "/bin/cli.py", REQ_PATH + "/bin/hpecp") 37 | 38 | # make executable 39 | os.chmod(REQ_PATH + "/bin/hpecp", 509) 40 | 41 | 42 | def read(rel_path): 43 | here = os.path.abspath(os.path.dirname(__file__)) 44 | with codecs.open(os.path.join(here, rel_path), "r") as fp: 45 | return fp.read() 46 | 47 | 48 | def get_version(rel_path): 49 | for line in read(rel_path).splitlines(): 50 | if line.startswith("__version__"): 51 | delim = '"' if '"' in line else "'" 52 | return line.split(delim)[1] 53 | else: 54 | raise RuntimeError("Unable to find version string.") 55 | 56 | 57 | try: 58 | this_directory = os.path.abspath(os.path.dirname(__file__)) 59 | with open(os.path.join(this_directory, "README.md")) as f: 60 | long_description = f.read() 61 | except Exception: 62 | long_description = "" 63 | 64 | 65 | setup( 66 | name="hpecp", 67 | description="HPE Ezmeral Container Platform client", 68 | long_description=long_description, 69 | long_description_content_type="text/markdown", 70 | author="Chris Snow", 71 | author_email="chsnow123@gmail.com", 72 | url="https://github.com/hpe-container-platform-community/hpecp-python-library", 73 | packages=["hpecp", "hpecp.cli"], 74 | package_data={"": ["requirements.txt", "LICENSE"]}, 75 | scripts=["bin/hpecp"], 76 | keywords="", 77 | version=get_version("hpecp/__init__.py"), 78 | install_requires=requirements, 79 | test_suite="nose.collector", 80 | tests_require=["coverage", "mock", "nose", "requests"], 81 | classifiers=[ 82 | "License :: OSI Approved :: MIT License", 83 | "Programming Language :: Python", 84 | "Programming Language :: Python :: 2.7", 85 | "Programming Language :: Python :: 3.5", 86 | "Programming Language :: Python :: 3.6", 87 | "Programming Language :: Python :: 3.7", 88 | "Programming Language :: Python :: 3.8", 89 | ], 90 | ) 91 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpe-container-platform-community/hpecp-python-library/6fb16af433663887768308e1e6eb9f408ef6bd9f/tests/__init__.py -------------------------------------------------------------------------------- /tests/base_resource_test.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | import unittest 22 | 23 | from hpecp.base_resource import ( 24 | AbstractResourceController, 25 | AbstractWaitableResourceController, 26 | ) 27 | from hpecp.client import ContainerPlatformClient 28 | 29 | 30 | class TestBaseResource(unittest.TestCase): 31 | def test_getters_and_setters(self): 32 | client = ContainerPlatformClient( 33 | username="test", 34 | password="test", 35 | api_host="test", 36 | api_port=8080, 37 | use_ssl=True, 38 | verify_ssl=True, 39 | warn_ssl=True, 40 | ) 41 | 42 | class ImplClass(AbstractResourceController): 43 | base_resource_path = "abc" 44 | resource_class = "abc" 45 | resource_list_path = "abc" 46 | 47 | c = ImplClass(client) 48 | 49 | c._set_base_resource_path("test_base_resource_path") 50 | c._set_resource_class("test_resource_class") 51 | c._set_resource_list_path("test_resource_list_path") 52 | 53 | self.assertEqual( 54 | c._get_base_resource_path(), "test_base_resource_path" 55 | ) 56 | self.assertEqual(c._get_resource_class(), "test_resource_class") 57 | self.assertEqual( 58 | c._get_resource_list_path(), "test_resource_list_path" 59 | ) 60 | 61 | class ImplWaitClass(AbstractWaitableResourceController): 62 | status_class = "abc" 63 | status_fieldname = "abc" 64 | base_resource_path = "abc" 65 | resource_class = "abc" 66 | resource_list_path = "abc" 67 | 68 | c = ImplWaitClass(client) 69 | 70 | c._set_status_class("test_status_class") 71 | c._set_status_fieldname("test_status_fieldname") 72 | 73 | self.assertEqual(c._get_status_class(), "test_status_class") 74 | self.assertEqual(c._get_status_fieldname(), "test_status_fieldname") 75 | -------------------------------------------------------------------------------- /tests/cli_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | BaseTestCase.registerHttpGetHandler( 27 | url="https://127.0.0.1:8080/some/url", 28 | response=MockResponse( 29 | json_data={"foo": "bar"}, 30 | text_data='{"foo":"bar"}', 31 | status_code=200, 32 | headers=dict(), 33 | ), 34 | ) 35 | 36 | BaseTestCase.registerHttpPostHandler( 37 | url="https://127.0.0.1:8080/some/url", 38 | response=MockResponse( 39 | text_data={"mock_data": True}, 40 | json_data={}, 41 | status_code=200, 42 | headers={}, 43 | ), 44 | ) 45 | 46 | BaseTestCase.registerHttpPutHandler( 47 | url="https://127.0.0.1:8080/some/url", 48 | response=MockResponse( 49 | text_data={"mock_data": True}, 50 | json_data={}, 51 | status_code=200, 52 | headers={}, 53 | ), 54 | ) 55 | -------------------------------------------------------------------------------- /tests/client_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | # Mock http (not https) session 28 | BaseTestCase.registerHttpPostHandler( 29 | "http://127.0.0.1:8080/api/v1/login", 30 | MockResponse( 31 | json_data={}, 32 | status_code=200, 33 | headers={ 34 | "location": ( 35 | "/api/v1/session/df1bfacb-ssl-false-xxxx-c8f57d8f3c72" 36 | ) 37 | }, 38 | ), 39 | ) 40 | -------------------------------------------------------------------------------- /tests/config_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | BaseTestCase.registerHttpPostHandler( 28 | url="https://127.0.0.1:8080/api/v2/config/auth", 29 | response=MockResponse( 30 | json_data={}, 31 | status_code=200, 32 | headers={ 33 | "location": ( 34 | "/api/v1/session/df1bfacb-xxxx-xxxx-xxxx-c8f57d8f3c71" 35 | ) 36 | }, 37 | ), 38 | ) 39 | -------------------------------------------------------------------------------- /tests/config_test.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from mock import patch 22 | 23 | from hpecp import ContainerPlatformClient 24 | 25 | from .base import BaseTestCase 26 | from .config_mock_api_responses import mockApiSetup 27 | 28 | # setup the mock data 29 | mockApiSetup() 30 | 31 | 32 | class TestTentants(BaseTestCase): 33 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 34 | def test_epic_tenant_list(self, mock_post): 35 | 36 | client = ContainerPlatformClient( 37 | username="admin", 38 | password="admin123", 39 | api_host="127.0.0.1", 40 | api_port=8080, 41 | use_ssl=True, 42 | ) 43 | client.create_session() 44 | 45 | client.config.auth( 46 | { 47 | "external_identity_server": { 48 | "bind_pwd": "5ambaPwd@", 49 | "user_attribute": "sAMAccountName", 50 | "bind_type": "search_bind", 51 | "bind_dn": ( 52 | "cn=Administrator,CN=Users,DC=samdom" 53 | ",DC=example,DC=com" 54 | ), 55 | "host": "1.1.1.1", 56 | "security_protocol": "ldaps", 57 | "base_dn": "CN=Users,DC=samdom,DC=example,DC=com", 58 | "verify_peer": False, 59 | "type": "Active Directory", 60 | "port": 636, 61 | } 62 | } 63 | ) 64 | -------------------------------------------------------------------------------- /tests/k8s_worker_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | BaseTestCase.registerHttpGetHandler( 28 | url="https://127.0.0.1:8080/api/v2/worker/k8shost", 29 | response=MockResponse( 30 | json_data={ 31 | "_embedded": { 32 | "k8shosts": [ 33 | { 34 | "status": "unlicensed", 35 | "propinfo": { 36 | "bds_storage_apollo": "false", 37 | "bds_network_publicinterface": "ens5", 38 | }, 39 | "approved_worker_pubkey": [], 40 | "tags": [], 41 | "hostname": ( 42 | "ip-10-1-0-238.eu-west-2.compute.internal" 43 | ), 44 | "ipaddr": "10.1.0.238", 45 | "setup_log": ( 46 | "/var/log/bluedata/install/" 47 | "k8shost_setup_10.1.0.238-" 48 | "2020-4-26-18-41-16" 49 | ), 50 | "_links": { 51 | "self": {"href": "/api/v2/worker/k8shost/4"} 52 | }, 53 | "sysinfo": { 54 | "network": [], 55 | "keys": { 56 | "reported_worker_public_key": ( 57 | "ssh-rsa ...== server\n" 58 | ) 59 | }, 60 | "storage": [], 61 | "swap": {"swap_total": 0}, 62 | "memory": {"mem_total": 65842503680}, 63 | "gpu": {"gpu_count": 0}, 64 | "cpu": { 65 | "cpu_logical_cores": 16, 66 | "cpu_count": 8, 67 | "cpu_physical_cores": 8, 68 | "cpu_sockets": 1, 69 | }, 70 | "mountpoint": [], 71 | }, 72 | }, 73 | { 74 | "status": "bundle", 75 | "approved_worker_pubkey": [], 76 | "tags": [], 77 | "hostname": "", 78 | "ipaddr": "10.1.0.186", 79 | "setup_log": ( 80 | "/var/log/bluedata/install/" 81 | "k8shost_setup_10.1.0.186-" 82 | "2020-4-26-18-49-10" 83 | ), 84 | "_links": { 85 | "self": {"href": "/api/v2/worker/k8shost/5"} 86 | }, 87 | }, 88 | ] 89 | } 90 | }, 91 | status_code=200, 92 | headers={}, 93 | ), 94 | ) 95 | 96 | BaseTestCase.registerHttpGetHandler( 97 | url="https://127.0.0.1:8080/api/v2/worker/k8shost/5", 98 | response=MockResponse( 99 | json_data={ 100 | "status": "bundle", 101 | "approved_worker_pubkey": [], 102 | "tags": [], 103 | "hostname": "", 104 | "ipaddr": "10.1.0.186", 105 | "setup_log": ( 106 | "/var/log/bluedata/install/" 107 | "k8shost_setup_10.1.0.186-" 108 | "2020-4-26-18-49-10" 109 | ), 110 | "_links": {"self": {"href": "/api/v2/worker/k8shost/5"}}, 111 | }, 112 | status_code=200, 113 | headers={}, 114 | ), 115 | ) 116 | 117 | BaseTestCase.registerHttpGetHandler( 118 | url="https://127.0.0.1:8080/api/v2/worker/k8shost/5?setup_log=true", 119 | response=MockResponse( 120 | json_data={ 121 | "status": "bundle", 122 | "approved_worker_pubkey": [], 123 | "tags": [], 124 | "hostname": "", 125 | "ipaddr": "10.1.0.186", 126 | "setup_log": ( 127 | "/var/log/bluedata/install/" 128 | "k8shost_setup_10.1.0.186-" 129 | "2020-4-26-18-49-10" 130 | ), 131 | "_links": {"self": {"href": "/api/v2/worker/k8shost/5"}}, 132 | }, 133 | status_code=200, 134 | headers={}, 135 | ), 136 | ) 137 | 138 | BaseTestCase.registerHttpGetHandler( 139 | url="https://127.0.0.1:8080/api/v2/worker/k8shost/8", 140 | response=MockResponse( 141 | json_data={}, 142 | status_code=404, 143 | raise_for_status_flag=True, 144 | headers={}, 145 | ), 146 | ) 147 | 148 | BaseTestCase.registerHttpPostHandler( 149 | url="https://127.0.0.1:8080/api/v2/worker/k8shost/5", 150 | response=MockResponse(json_data={}, status_code=204, headers={}), 151 | ) 152 | 153 | BaseTestCase.registerHttpPostHandler( 154 | url="https://127.0.0.1:8080/api/v2/worker/k8shost/", 155 | response=MockResponse( 156 | json_data={}, 157 | status_code=201, 158 | headers={"location": "/new/cluster/id"}, 159 | ), 160 | ) 161 | -------------------------------------------------------------------------------- /tests/license_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | BaseTestCase.registerHttpPostHandler( 28 | url="https://127.0.0.1:8080/api/v2/hpelicense", 29 | response=MockResponse( 30 | json_data={}, 31 | status_code=201, 32 | headers={"location": "/api/v2/hpeclicense/1"}, 33 | ), 34 | ) 35 | 36 | BaseTestCase.registerHttpDeleteHandler( 37 | url="https://127.0.0.1:8080/api/v2/hpelicense/TEST_LICENSE_KEY/", 38 | response=MockResponse( 39 | json_data={}, 40 | status_code=200, 41 | headers=dict(), 42 | ), 43 | ) 44 | 45 | BaseTestCase.registerHttpGetHandler( 46 | url="https://127.0.0.1:8080/api/v1/license", 47 | response=MockResponse( 48 | json_data={ 49 | "_links": {"self": {"href": "/api/v1/license"}}, 50 | "state": "unlicensed", 51 | "uuid": "3c831f6e-f76f-410d-977c-ed13b0c817d1", 52 | }, 53 | status_code=200, 54 | headers=dict(), 55 | ), 56 | ) 57 | 58 | BaseTestCase.registerHttpGetHandler( 59 | url="https://127.0.0.1:8080/api/v2/hpelicense", 60 | response=MockResponse( 61 | json_data={ 62 | "_links": {"self": {"href": "/api/v2/hpelicense"}}, 63 | "Licenses": [ 64 | { 65 | "Label": "The License", 66 | "Feature": "HPE Machine Learning Ops", 67 | "Capacity": 240, 68 | "UnlimitedCapacity": False, 69 | "Start": 1566864000000, 70 | "StartDisplay": "2019-08-27T00:00:00Z", 71 | "Expiration": 1609286399000, 72 | "ExpirationDisplay": "2020-12-29T23:59:59Z", 73 | "LicenseKey": "TEST_LICENSE_KEY", 74 | "DeviceID": "1234 1234", 75 | "Evaluation": False, 76 | } 77 | ], 78 | "Summaries": [ 79 | { 80 | "Label": "HPE Container Platform", 81 | "UnlimitedCapacity": False, 82 | "TotalCapacity": 240, 83 | "UsedCapacity": 24, 84 | "AvailableCapacity": 216, 85 | "NextExpiration": 1609286399000, 86 | "NextExpirationDisplay": "2020-12-29T23:59:59Z", 87 | "LatestExpiration": 1609286399000, 88 | "LatestExpirationDisplay": "2020-12-29T23:59:59Z", 89 | "Valid": True, 90 | "ValidationTime": 1594758782000, 91 | "RevalidateTime": 1609286400000, 92 | }, 93 | { 94 | "Label": "HPE Machine Learning Ops", 95 | "UnlimitedCapacity": False, 96 | "TotalCapacity": 240, 97 | "UsedCapacity": 0, 98 | "AvailableCapacity": 240, 99 | "NextExpiration": 1609286399000, 100 | "NextExpirationDisplay": "2020-12-29T23:59:59Z", 101 | "LatestExpiration": 1609286399000, 102 | "LatestExpirationDisplay": "2020-12-29T23:59:59Z", 103 | "Valid": True, 104 | "ValidationTime": 1594758782000, 105 | "RevalidateTime": 1609286400000, 106 | }, 107 | ], 108 | "Messages": [], 109 | "Valid": True, 110 | "Enabled": True, 111 | "ValidationTime": 1594758782000, 112 | "RevalidateTime": 1609286400000, 113 | }, 114 | status_code=200, 115 | headers=dict(), 116 | ), 117 | ) 118 | -------------------------------------------------------------------------------- /tests/lock_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | BaseTestCase.registerHttpGetHandler( 28 | url="https://127.0.0.1:8080/api/v1/lock", 29 | response=MockResponse( 30 | json_data={ 31 | "_links": {"self": {"href": "/api/v1/lock"}}, 32 | "locked": False, 33 | "_embedded": {"internal_locks": [], "external_locks": []}, 34 | }, 35 | status_code=200, 36 | headers=dict(), 37 | ), 38 | ) 39 | 40 | BaseTestCase.registerHttpPostHandler( 41 | url="https://127.0.0.1:8080/api/v1/lock", 42 | response=MockResponse( 43 | json_data={}, 44 | status_code=201, 45 | headers={"Location": "/test_location/1"}, 46 | ), 47 | ) 48 | 49 | BaseTestCase.registerHttpDeleteHandler( 50 | url="https://127.0.0.1:8080/api/v1/lock/1", 51 | response=MockResponse( 52 | json_data={}, 53 | status_code=201, 54 | headers=dict(), 55 | ), 56 | ) 57 | -------------------------------------------------------------------------------- /tests/role_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | BaseTestCase.registerHttpGetHandler( 28 | url="https://127.0.0.1:8080/api/v1/role/1", 29 | response=MockResponse( 30 | json_data={ 31 | "_links": { 32 | "self": {"href": "/api/v1/role/1"}, 33 | "all_roles": {"href": "/api/v1/role"}, 34 | }, 35 | "label": { 36 | "name": "Site Admin", 37 | "description": "Role for Site Admin", 38 | }, 39 | }, 40 | status_code=200, 41 | headers={}, 42 | ), 43 | ) 44 | -------------------------------------------------------------------------------- /tests/role_test.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | import json 22 | from unittest import TestCase 23 | 24 | import six 25 | from mock import patch 26 | 27 | from .base import BaseTestCase, get_client 28 | from .role_mock_api_responses import mockApiSetup 29 | 30 | # setup the mock data 31 | mockApiSetup() 32 | 33 | 34 | class TestRoleGet(TestCase): 35 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 36 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 37 | def test_get_role_assertions(self, mock_get, mock_post): 38 | 39 | with self.assertRaisesRegexp( 40 | AssertionError, 41 | "'id' must be provided and must be a str", 42 | ): 43 | get_client().role.get(123) 44 | 45 | # pylint: disable=anomalous-backslash-in-string 46 | with self.assertRaisesRegexp( 47 | AssertionError, 48 | "'id' does not start with '/api/v1/role/", 49 | ): 50 | get_client().role.get("garbage") 51 | 52 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 53 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 54 | def test_get_role(self, mock_get, mock_post): 55 | 56 | role = get_client().role.get("/api/v1/role/1") 57 | 58 | self.assertEqual(role.id, "/api/v1/role/1") 59 | self.assertEqual(role.name, "Site Admin") 60 | self.assertEqual(role.description, "Role for Site Admin") 61 | 62 | 63 | class TestCLI(BaseTestCase): 64 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 65 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 66 | def test_get(self, mock_post, mock_delete): 67 | 68 | try: 69 | hpecp = self.cli.CLI() 70 | hpecp.role.get("/api/v1/role/1") 71 | except Exception as e: 72 | # Unexpected Exception 73 | self.fail(e) 74 | 75 | stdout = self.out.getvalue().strip() 76 | stderr = self.err.getvalue().strip() 77 | 78 | expected_stdout = """\ 79 | _links: 80 | all_roles: 81 | href: /api/v1/role 82 | self: 83 | href: /api/v1/role/1 84 | label: 85 | description: Role for Site Admin 86 | name: Site Admin""" 87 | 88 | expected_stderr = "" 89 | 90 | self.assertEqual(stdout, expected_stdout) 91 | 92 | # coverage seems to populate standard error on PY3 (issues 93) 93 | if six.PY2: 94 | self.assertEqual(stderr, expected_stderr) 95 | 96 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 97 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 98 | def test_get_json(self, mock_post, mock_delete): 99 | 100 | try: 101 | hpecp = self.cli.CLI() 102 | hpecp.role.get("/api/v1/role/1", output="json") 103 | except Exception as e: 104 | # Unexpected Exception 105 | self.fail(e) 106 | 107 | stdout = self.out.getvalue().strip() 108 | stderr = self.err.getvalue().strip() 109 | 110 | stdout = json.dumps(json.loads(stdout), sort_keys=True) 111 | 112 | expected_stdout = json.dumps( 113 | { 114 | "label": { 115 | "description": "Role for Site Admin", 116 | "name": "Site Admin", 117 | }, 118 | "_links": { 119 | "all_roles": {"href": "/api/v1/role"}, 120 | "self": {"href": "/api/v1/role/1"}, 121 | }, 122 | }, 123 | sort_keys=True, 124 | ) 125 | 126 | expected_stderr = "" 127 | 128 | self.assertEqual(stdout, expected_stdout) 129 | 130 | # coverage seems to populate standard error on PY3 (issues 93) 131 | if six.PY2: 132 | self.assertEqual(stderr, expected_stderr) 133 | -------------------------------------------------------------------------------- /tests/tenant_test.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from mock import patch 22 | 23 | from hpecp.exceptions import APIItemNotFoundException 24 | 25 | from .base import BaseTestCase, get_client 26 | from .tenant_mock_api_responses import mockApiSetup 27 | 28 | # setup the mock data 29 | mockApiSetup() 30 | 31 | 32 | class TestTentants(BaseTestCase): 33 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 34 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 35 | def test_tenant_list(self, mock_get, mock_post): 36 | 37 | client = get_client() 38 | 39 | # Makes GET Request: https://127.0.0.1:8080/api/v1/tenant 40 | tenants = client.tenant.list() 41 | 42 | # Test that json response is saved in each Tenant object 43 | self.assertIsNotNone(client.tenant.list()[0].json) 44 | 45 | # Test TenantList subscriptable access and Tenant property setters 46 | self.assertEqual(tenants[0].id, "/api/v1/tenant/1") 47 | self.assertEqual(tenants[0].status, "ready") 48 | self.assertEqual(tenants[0].name, "Site Admin") 49 | self.assertEqual(tenants[0].tenant_type, "docker") 50 | self.assertEqual( 51 | tenants[0].description, "Site Admin Tenant for BlueData clusters" 52 | ) 53 | 54 | # Test TenantList iterators 55 | self.assertEqual( 56 | [tenant.id for tenant in client.tenant.list()], 57 | ["/api/v1/tenant/1", "/api/v1/tenant/2"], 58 | ) 59 | 60 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 61 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 62 | def test_get_tenant_id_format(self, mock_get, mock_post): 63 | client = get_client() 64 | 65 | with self.assertRaisesRegexp( 66 | AssertionError, 67 | ("'id' does not start with '/api/v1/tenant/'"), 68 | ): 69 | client.tenant.get("garbage") 70 | 71 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 72 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 73 | def test_get_tenant(self, mock_get, mock_post): 74 | tenant = get_client().tenant.get("/api/v1/tenant/1") 75 | self.assertEqual(tenant.id, "/api/v1/tenant/1") 76 | 77 | tenant = get_client().tenant.get("/api/v1/tenant/2") 78 | self.assertEqual(tenant.id, "/api/v1/tenant/2") 79 | 80 | with self.assertRaises(APIItemNotFoundException): 81 | get_client().tenant.get("/api/v1/tenant/100") 82 | -------------------------------------------------------------------------------- /tests/user_mock_api_responses.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | from .base import BaseTestCase, MockResponse 23 | 24 | 25 | def mockApiSetup(): 26 | 27 | BaseTestCase.registerHttpGetHandler( 28 | url="https://127.0.0.1:8080/api/v1/user/", 29 | response=MockResponse( 30 | json_data={ 31 | "_embedded": { 32 | "users": [ 33 | { 34 | "_links": {"self": {"href": "/api/v1/user/16"}}, 35 | "label": {"name": "csnow", "description": "chris"}, 36 | "is_group_added_user": False, 37 | "is_external": False, 38 | "is_service_account": False, 39 | "default_tenant": "", 40 | "is_siteadmin": False, 41 | }, 42 | { 43 | "_links": {"self": {"href": "/api/v1/user/5"}}, 44 | "label": { 45 | "name": "admin", 46 | "description": "BlueData Administrator", 47 | }, 48 | "is_group_added_user": False, 49 | "is_external": False, 50 | "is_service_account": False, 51 | "default_tenant": "/api/v1/tenant/1", 52 | "is_siteadmin": True, 53 | }, 54 | ] 55 | } 56 | }, 57 | status_code=200, 58 | headers={}, 59 | ), 60 | ) 61 | 62 | BaseTestCase.registerHttpGetHandler( 63 | url="https://127.0.0.1:8080/api/v1/user/16/", 64 | response=MockResponse( 65 | json_data={ 66 | "_links": {"self": {"href": "/api/v1/user/16"}}, 67 | "label": {"name": "csnow", "description": "chris"}, 68 | "is_group_added_user": False, 69 | "is_external": False, 70 | "is_service_account": False, 71 | "default_tenant": "", 72 | "is_siteadmin": False, 73 | }, 74 | status_code=200, 75 | headers={}, 76 | ), 77 | ) 78 | 79 | BaseTestCase.registerHttpGetHandler( 80 | url="https://127.0.0.1:8080/api/v1/user/123", 81 | response=MockResponse( 82 | json_data={ 83 | "_links": {"self": {"href": "/api/v1/user/123"}}, 84 | "purpose": "proxy", 85 | }, 86 | status_code=200, 87 | headers={}, 88 | ), 89 | ) 90 | 91 | BaseTestCase.registerHttpGetHandler( 92 | url="https://127.0.0.1:8080/api/v1/user/999", 93 | response=MockResponse( 94 | text_data="Not found.", 95 | json_data={}, 96 | status_code=404, 97 | raise_for_status_flag=True, 98 | headers={}, 99 | ), 100 | ) 101 | 102 | BaseTestCase.registerHttpPostHandler( 103 | url="https://127.0.0.1:8080/api/v1/user", 104 | response=MockResponse( 105 | json_data={}, 106 | status_code=200, 107 | headers={"location": ("/mock/api/user/1")}, 108 | ), 109 | ) 110 | 111 | BaseTestCase.registerHttpDeleteHandler( 112 | url="https://127.0.0.1:8080/api/v1/user/999", 113 | response=MockResponse( 114 | text_data="Not found.", 115 | json_data={}, 116 | status_code=404, 117 | raise_for_status_flag=True, 118 | headers={}, 119 | ), 120 | ) 121 | 122 | BaseTestCase.registerHttpDeleteHandler( 123 | url="https://127.0.0.1:8080/api/v1/user/123", 124 | response=MockResponse( 125 | text_data="", 126 | json_data={}, 127 | status_code=200, 128 | headers={}, 129 | ), 130 | ) 131 | -------------------------------------------------------------------------------- /tests/user_test.py: -------------------------------------------------------------------------------- 1 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | from unittest import TestCase 22 | 23 | import six 24 | from mock import patch 25 | 26 | from hpecp import ContainerPlatformClient 27 | from hpecp.exceptions import APIItemNotFoundException 28 | 29 | from .base import BaseTestCase, get_client 30 | from .user_mock_api_responses import mockApiSetup 31 | 32 | # setup the mock data 33 | mockApiSetup() 34 | 35 | 36 | class TestUsers(TestCase): 37 | @patch("requests.get", side_effect=BaseTestCase.httpGetHandlers) 38 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 39 | def test_get_users(self, mock_get, mock_post): 40 | client = ContainerPlatformClient( 41 | username="admin", 42 | password="admin123", 43 | api_host="127.0.0.1", 44 | api_port=8080, 45 | use_ssl=True, 46 | ) 47 | 48 | # Makes POST Request: https://127.0.0.1:8080/api/v1/login 49 | client.create_session() 50 | 51 | # Makes GET Request: https://127.0.0.1:8080/api/v1/user 52 | users = client.user.list() 53 | 54 | # Test that json response is saved in each WorkerK8s object 55 | assert users[0].json is not None 56 | 57 | # Test UserList subscriptable access and property setters 58 | assert users[0].is_service_account is False 59 | assert users[0].is_siteadmin is False 60 | assert users[0].default_tenant == "" 61 | assert users[0].is_external is False 62 | assert users[0].is_group_added_user is False 63 | 64 | assert users[0].name == "csnow" 65 | assert users[0].description == "chris" 66 | assert users[0]._links == {"self": {"href": "/api/v1/user/16"}} 67 | 68 | 69 | class TestDeleteUser(TestCase): 70 | @patch("requests.delete", side_effect=BaseTestCase.httpDeleteHandlers) 71 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 72 | def test_delete_user(self, mock_post, mock_delete): 73 | with self.assertRaisesRegexp( 74 | AssertionError, 75 | "'id' must be provided and must be a str", 76 | ): 77 | get_client().user.delete(id=999) 78 | 79 | with self.assertRaisesRegexp( 80 | AssertionError, 81 | "'id' does not start with '/api/v1/user/'", 82 | ): 83 | get_client().user.delete(id="garbage") 84 | 85 | with self.assertRaises(APIItemNotFoundException): 86 | get_client().user.delete(id="/api/v1/user/999") 87 | 88 | get_client().user.delete(id="/api/v1/user/123") 89 | 90 | 91 | class TestCLI(BaseTestCase): 92 | @patch("requests.post", side_effect=BaseTestCase.httpPostHandlers) 93 | def test_create(self, mock_post): 94 | 95 | hpecp = self.cli.CLI() 96 | hpecp.user.create( 97 | name="jdoe", 98 | password="secret", 99 | description="Jane Doe", 100 | is_external=False, 101 | ) 102 | 103 | stdout = self.out.getvalue().strip() 104 | stderr = self.err.getvalue().strip() 105 | 106 | expected_stdout = "/mock/api/user/1" 107 | expected_stderr = "" 108 | 109 | self.assertEqual(stdout, expected_stdout) 110 | 111 | # coverage seems to populate standard error on PY3 (issues 93) 112 | if six.PY2: 113 | self.assertEqual(stderr, expected_stderr) 114 | -------------------------------------------------------------------------------- /theia_git_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git config credential.https://github.com.username $GIT_USER 4 | 5 | git_url=$(git config --get remote.origin.url) 6 | 7 | USER=$(echo $git_url | sed 's/.*://' | sed 's/\/.*//') 8 | REPO=$(echo $git_url | sed 's/.*://' | sed 's/.*\///') 9 | 10 | if [[ git_url != "https://"** ]]; 11 | then 12 | echo "You must use the 'https://github.com/...' git url and not 'git@github.com:..'" 13 | echo "you can set this with:" 14 | 15 | echo "git remote set-url origin https://github.com/$USER/$REPO" 16 | exit 1 17 | fi -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # tox (https://tox.readthedocs.io/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py27, py35, py36, py37, py38, py39 8 | skip_missing_interpreters = True 9 | 10 | [gh-actions] 11 | python = 12 | 2.7: py27 13 | 3.5: py35 14 | 3.6: py36 15 | 3.7: py37 16 | 3.8: py38 17 | 18 | [testenv] 19 | commands = nosetests {posargs} 20 | deps = 21 | jinja2 22 | mock 23 | nose 24 | requests 25 | jmespath 26 | fire 27 | setenv = TOX_BUILD_DIR = {toxinidir} 28 | 29 | [testenv:py27] 30 | ; recreate due to ThreadingTCPServer import error 31 | recreate = true 32 | 33 | [pytest] 34 | addopts = -s 35 | -------------------------------------------------------------------------------- /utils/hpecp_cli_conf.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | set -e 25 | 26 | if [[ ! -d ~/.aws ]]; then 27 | if [[ ! -d /workspace/.aws ]]; then 28 | echo "Please run utils/hpecp_configure.sh" 29 | exit 1 30 | else 31 | ln -sf /workspace/.aws ~/.aws 32 | fi 33 | fi 34 | 35 | if [[ ! -f ~/.hpecp_service ]]; then 36 | if [[ ! -f /workspace/.hpecp_service ]]; then 37 | echo "Please run utils/hpecp_configure.sh" 38 | exit 1 39 | else 40 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 41 | fi 42 | fi 43 | 44 | source ~/.hpecp_service 45 | 46 | CONTROLLER_IP=$(aws ec2 describe-instances --instance-ids $CONTROLLER_INSTANCE_ID --output text --query "Reservations[*].Instances[*].[PublicIpAddress]") 47 | 48 | if [[ "${INSTALL_WITH_SSL}" == 'true' ]]; then 49 | SSL=True 50 | else 51 | SSL=False 52 | fi 53 | 54 | echo "[default] 55 | api_host = ${CONTROLLER_IP} 56 | api_port = 8080 57 | use_ssl = ${SSL} 58 | verify_ssl = False 59 | warn_ssl = False 60 | username = admin 61 | password = admin123 62 | " 63 | 64 | -------------------------------------------------------------------------------- /utils/hpecp_configure.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | set -e 25 | 26 | # NOTE: we save settings to /workspace as the $HOME folder isn't persisted in gitpod 27 | 28 | [[ -f ~/.hpecp_service ]] && echo Aborting '~/.hpecp_service' exists && exit 1 29 | [[ -d ~/.aws ]] && echo 'Aborting ~/.aws exists' && exit 1 30 | 31 | rm -f /workspace/.hpecp_service 32 | rm -rf /workspace/.aws 33 | 34 | if [[ ! -f ~/.hpecp_service ]]; then 35 | echo "Enter your HPECP service details (enter empty line to finish):" 36 | 37 | while read line 38 | do 39 | # break if the line is empty 40 | [ -z "$line" ] && break 41 | echo "$line" >> "/workspace/.hpecp_service" 42 | done 43 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 44 | fi 45 | source ~/.hpecp_service 46 | 47 | if [[ ! -f ~/.aws ]]; then 48 | mkdir /workspace/.aws 49 | cat <<-EOF > /workspace/.aws/credentials 50 | [default] 51 | aws_secret_access_key = ${AWS_SECRET_KEY} 52 | aws_access_key_id = ${AWS_ACCESS_KEY} 53 | EOF 54 | cat <<-EOF > /workspace/.aws/config 55 | [default] 56 | region = ${AWS_REGION} 57 | EOF 58 | ln -sf /workspace/.aws ~/.aws 59 | fi 60 | -------------------------------------------------------------------------------- /utils/hpecp_controller_ip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | set -e 25 | 26 | if [[ ! -d ~/.aws ]]; then 27 | if [[ ! -d /workspace/.aws ]]; then 28 | echo "Please run utils/hpecp_configure.sh" 29 | exit 1 30 | else 31 | ln -sf /workspace/.aws ~/.aws 32 | fi 33 | fi 34 | 35 | if [[ ! -f ~/.hpecp_service ]]; then 36 | if [[ ! -f /workspace/.hpecp_service ]]; then 37 | echo "Please run utils/hpecp_configure.sh" 38 | exit 1 39 | else 40 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 41 | fi 42 | fi 43 | 44 | source ~/.hpecp_service 45 | 46 | aws ec2 describe-instances --instance-ids $CONTROLLER_INSTANCE_ID --output text --query "Reservations[*].Instances[*].[PublicIpAddress]" 47 | 48 | -------------------------------------------------------------------------------- /utils/hpecp_firewall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | 25 | if [[ ! -d ~/.aws ]]; then 26 | if [[ ! -d /workspace/.aws ]]; then 27 | echo "Please run utils/hpecp_configure.sh" 28 | exit 1 29 | else 30 | ln -sf /workspace/.aws ~/.aws 31 | fi 32 | fi 33 | 34 | if [[ ! -f ~/.hpecp_service ]]; then 35 | if [[ ! -f /workspace/.hpecp_service ]]; then 36 | echo "Please run utils/hpecp_configure.sh" 37 | exit 1 38 | else 39 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 40 | fi 41 | fi 42 | source ~/.hpecp_service 43 | 44 | aws ec2 create-network-acl-entry \ 45 | --network-acl-id $NACL_ID \ 46 | --cidr-block "$(curl -s http://ifconfig.me/ip)/32" \ 47 | --ingress \ 48 | --protocol -1 \ 49 | --rule-action allow \ 50 | --rule-number 110 51 | 52 | if [[ $? != 0 ]]; then 53 | aws ec2 replace-network-acl-entry \ 54 | --network-acl-id $NACL_ID \ 55 | --cidr-block "$(curl -s http://ifconfig.me/ip)/32" \ 56 | --ingress \ 57 | --protocol -1 \ 58 | --rule-action allow \ 59 | --rule-number 110 60 | fi 61 | 62 | aws ec2 authorize-security-group-ingress \ 63 | --group-id $SG_ID \ 64 | --protocol all \ 65 | --port -1 \ 66 | --cidr "$(curl -s http://ifconfig.me/ip)/32" 67 | -------------------------------------------------------------------------------- /utils/hpecp_proxy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | # TODO https://www.scaleway.com/en/docs/how-to-configure-nginx-reverse-proxy/ 24 | 25 | echo "Not Implemented Yet" 26 | exit 1 -------------------------------------------------------------------------------- /utils/hpecp_start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | set -e 25 | 26 | if [[ ! -d ~/.aws ]]; then 27 | if [[ ! -d /workspace/.aws ]]; then 28 | echo "Please run utils/hpecp_configure.sh" 29 | exit 1 30 | else 31 | ln -sf /workspace/.aws ~/.aws 32 | fi 33 | fi 34 | 35 | if [[ ! -f ~/.hpecp_service ]]; then 36 | if [[ ! -f /workspace/.hpecp_service ]]; then 37 | echo "Please run utils/hpecp_configure.sh" 38 | exit 1 39 | else 40 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 41 | fi 42 | fi 43 | source ~/.hpecp_service 44 | 45 | aws ec2 start-instances --instance-ids $ALL_INSTANCE_IDS -------------------------------------------------------------------------------- /utils/hpecp_status.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | set -e 25 | 26 | if [[ ! -d ~/.aws ]]; then 27 | if [[ ! -d /workspace/.aws ]]; then 28 | echo "Please run utils/hpecp_configure.sh" 29 | exit 1 30 | else 31 | ln -sf /workspace/.aws ~/.aws 32 | fi 33 | fi 34 | 35 | if [[ ! -f ~/.hpecp_service ]]; then 36 | if [[ ! -f /workspace/.hpecp_service ]]; then 37 | echo "Please run utils/hpecp_configure.sh" 38 | exit 1 39 | else 40 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 41 | fi 42 | fi 43 | source ~/.hpecp_service 44 | 45 | aws ec2 describe-instance-status --instance-ids $ALL_INSTANCE_IDS --include-all-instances --output table --query "InstanceStatuses[*].{ID:InstanceId,State:InstanceState.Name}" -------------------------------------------------------------------------------- /utils/hpecp_stop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (C) Copyright [2020] Hewlett Packard Enterprise Development LP 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | # OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | set -u 24 | set -e 25 | 26 | if [[ ! -d ~/.aws ]]; then 27 | if [[ ! -d /workspace/.aws ]]; then 28 | echo "Please run utils/hpecp_configure.sh" 29 | exit 1 30 | else 31 | ln -sf /workspace/.aws ~/.aws 32 | fi 33 | fi 34 | 35 | if [[ ! -f ~/.hpecp_service ]]; then 36 | if [[ ! -f /workspace/.hpecp_service ]]; then 37 | echo "Please run utils/hpecp_configure.sh" 38 | exit 1 39 | else 40 | ln -sf /workspace/.hpecp_service ~/.hpecp_service 41 | fi 42 | fi 43 | source ~/.hpecp_service 44 | 45 | aws ec2 stop-instances --instance-ids $ALL_INSTANCE_IDS --------------------------------------------------------------------------------