Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
*.pyc
*.zip
examples/dumps
dist/
packages/openshift_client.egg-info/
build/
2 changes: 1 addition & 1 deletion ansible/rebuild_module.digest
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14fd6a307ac3c1c78d0a1e69452ae072 -
5989e72fd25bf177445364381d4ad2dd -

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions docs/PACKAGING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Openshift Python Client Packaging

## Introduction
This document primarily serves as a reference for us to publish the openshift-client module to PyPI for general consumption by our consumers. It can also be used by anyone interested in getting started with Python Packaging as all the documented steps and configurations can easily be migrated to any other package/module.

## Recommended Setup
### Create User Accounts
To work with packaging, you will need to create user accounts on one or both of the following sites:

#### PyPI - The Python Package Index
For **official** releases that are available for installation
* https://pypi.org/

#### TestPyPI - The Test Python Package Index
For **testing** python packaging without impacting the official index
* https://test.pypi.org/

### Generate API Tokens
For each account that you create, you can generate API Tokens that make publishing your packages/modules easier. Once the tokens have been generated, you can add them to your `~/.pypirc` file:

```text
[pypi]
username = __token__
password = pypi-<API TOKEN>

[testpypi]
repository: https://test.pypi.org/legacy/
username = __token__
password = pypi-<API TOKEN>
```

### setup.cfg
The openshift-client module has been tested to support both python2 and python3. Therefore, elect to build a `univeral` wheel instead of platform specific wheels. To do so, we have added the necessary flags to our `setup.cfg` file:
```text
[bdist_wheel]
universal = 1

[metadata]
license_file = LICENSE
```

The alternative is to add the necessary flag to the commandline when building your packages:

```bash
python setup.py build bdist_wheel --universal
```

## Building
For openshift-client, build both a source distribution and a universal wheel:
```bash
python setup.py build sdist bdist_wheel
```

## Publishing
Publishing to either package index is accomplished by using [Twine](https://pypi.org/project/twine/). Because we setup our local `~/.pypirc` above, we can reference the repository by the name defined therein instead of passing the full URL on the commandline.

### TestPyPI
```bash
twine upload --repository testpypi dist/*
```

### PyPI
```bash
twine upload --repository pypi dist/*
```

## Installation

### TestPyPI
Installation from TestPyPI must be performed using one of the following methods:

1. Latest version
```bash
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple openshift-client
```
2. Specific version
```bash
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple openshift-client==1.0.2
```

### PyPI
1. Latest version
```bash
pip install openshift-client
```

2. Specific version
```bash
pip install openshift-client==1.0.2
```

## Cleanup
If you're working on changes, you'll need to bump the version string for every publish to either index (releases are unique). To cleanup the artifacts from previous builds, you can execute the following:
```bash
rm -rf dist/ packages/openshift_client.egg-info/ build/
```

## Helpful Links
* https://packaging.python.org/guides/distributing-packages-using-setuptools/
* https://setuptools.readthedocs.io/en/latest/index.html
* https://packaging.python.org/guides/single-sourcing-package-version/
* https://packaging.python.org/guides/using-testpypi/
* https://packaging.python.org/tutorials/packaging-projects/
* https://github.com/pypa/sampleproject
* https://realpython.com/pypi-publish-python-package/
* https://the-hitchhikers-guide-to-packaging.readthedocs.io/en/latest/index.html
46 changes: 21 additions & 25 deletions examples/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,45 @@

from __future__ import print_function
from __future__ import absolute_import
from openshift import *

import openshift as oc
from openshift import null, Missing, OpenShiftPythonException

try:

print("Projects created by users:", \
oc.selector("projects").narrow(
lambda project: project.metadata.annotations["openshift.io/requester"] is not Missing
print("Projects created by users:", oc.selector("projects").narrow(
lambda prj: prj.metadata.annotations["openshift.io/requester"] is not Missing
).qnames())

oc.selector("projects").narrow(
# Eliminate any projects created by the system
lambda project: project.metadata.annotations["openshift.io/requester"] is not Missing
lambda prj: prj.metadata.annotations["openshift.io/requester"] is not Missing
).narrow(
# Select from user projects any which violate privileged naming convention
lambda project:
project.metadata.qname == "openshift" or
project.metadata.qname.startswith("openshift-") or
project.metadata.qname == "kubernetes" or
project.metadata.qname.startswith("kube-") or
project.metadata.qname.startswith("kubernetes-")
lambda prj:
prj.metadata.qname == "openshift" or
prj.metadata.qname.startswith("openshift-") or
prj.metadata.qname == "kubernetes" or
prj.metadata.qname.startswith("kube-") or
prj.metadata.qname.startswith("kubernetes-")
).for_each(
lambda project: error("Invalid project: %s" % project.metadata.qname)
lambda prj: oc.error("Invalid project: %s" % prj.metadata.qname)
)

with timeout(5):
with oc.timeout(5):
success, obj = oc.selector("pods").until_any(lambda pod: pod.status.phase == "Succeeded")
if success:
print("Found one pod was successful: " + str(obj))

with timeout(5):
with oc.timeout(5):
success, obj = oc.selector("pods").narrow("pod").until_any(
lambda pod: pod.status.conditions.can_match({"type": "Ready", "status": False, "reason": "PodCompleted"}))
if success:
print("Found one pod was successful: " + str(obj))

with oc.project("myproject") as project:


with project("myproject"):

oc.create_if_absent(
project.create_if_absent(
{
"apiVersion": "v1",
"kind": "User",
Expand All @@ -56,7 +55,7 @@
}
)

oc.create_if_absent(
project.create_if_absent(
{
"apiVersion": "v1",
"kind": "User",
Expand All @@ -71,7 +70,6 @@
}
)


pods = oc.selector("pod")
print("Pods: " + str(pods.qnames()))

Expand All @@ -84,7 +82,7 @@
print(str(user))

john = oc.selector("user/john")
john.label({"mylabel": None}) # remove a label
john.label({"mylabel": null}) # remove a label

label_selector = oc.selector("users", labels={"mylabel": "myvalue"})

Expand All @@ -98,7 +96,7 @@

users.label({"another_label": "another_value"})

john.patch({
john.object().patch({
"groups": null,
"identities": [
"github: 19783215"
Expand All @@ -117,7 +115,7 @@
if user.notthere.dontcare.wontbreak is not Missing:
print("Should see this, but also shouldn't see exception")

oc.delete_if_present("user/bark", "user/bite")
project.delete_if_present("user/bark", "user/bite")

bark_obj = {
"apiVersion": "v1",
Expand Down Expand Up @@ -157,7 +155,5 @@

bark_bite_sel.until_any(lambda obj: obj.metadata.qname == "bite")



except OpenShiftPythonException as e:
print("An exception occurred: " + str(e))
9 changes: 9 additions & 0 deletions packages/openshift/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@
from . import status
from . import config
from .ansible import ansible

# Single source for module version
__VERSION__ = '1.0.2'

null = None # Allow scripts to specify null in object definitions


# Allows modules to trigger errors
def error(msg, **kwargs):
raise OpenShiftPythonException(msg, **kwargs)


# Convenience method for accessing the module version
def get_module_version():
return __VERSION__
5 changes: 5 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[bdist_wheel]
universal = 1

[metadata]
license_file = LICENSE
22 changes: 20 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/python

import os
from setuptools import setup, find_packages


Expand All @@ -15,16 +16,33 @@ def get_long_description():
return open("README.md", "r").read()


def read(rel_path):
"""Returns the contents of the file at the specified relative path."""
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, rel_path), 'r') as fp:
return fp.read()


def get_version(rel_path):
"""Returns the semantic version for the openshift-client module."""
for line in read(rel_path).splitlines():
if line.startswith('__VERSION__'):
delim = '"' if '"' in line else "'"
return line.split(delim)[1]
else:
raise RuntimeError("Unable to find version string.")


setup(
name="openshift-client",
version="0.1.0",
version=get_version('packages/openshift/__init__.py'),
author="Justin Pierce",
author_email="jupierce@redhat.com",
maintainer="Brad Williams",
maintainer_email="brawilli@redhat.com",
url="https://github.com/openshift/openshift-client-python",
description="OpenShift python client",
packages=find_packages(include="openshift"),
packages=find_packages(where='packages'),
package_dir={"": "packages"},
install_requires=get_requirements(),
keywords=["OpenShift"],
Expand Down