Developer guide¶
Contributing¶
There are large parts of the Kubernetes API that are not covered by this library yet, but we welcome anyone who wishes to help us make it more complete.
If you want to contribute, read the rest of this guide, open an issue to discuss the changes you want to do (if you feel it is needed), and finally send us a Pull Request with your changes.
We strive to have good test coverage, and PRs with failing or ignored tests will not be accepted. We also encourage you to add at least a minimal set of tests for the new code you write. Since some parts of the library are harder to test than others, look at other, similar, parts of the library to see the level of testing wanted.
We use Prospector for code quality/style checking, and PRs failing this check might be required to fix any issues before being merged. The code style in the project is close to PEP8, so should not present any big problems.
Adding support for new object types¶
If you want to create support for a new type of object in the Kubernetes API, the best thing to start with is the Kubernetes API reference documentation. The first thing you need to do, is find the “top most” type, ie. the type you operate on through the API. We can call this an API type. Examples are Pod
, Service
or Ingress
.
Create a new module under k8s.models
if your type doesn’t belong in any of the existing ones, then start by creating a class inheriting from Model
named the same as the type is named in the Kubernetes documentation. Use the same casing as the Kubernetes documentation uses.
For your API type, inside the class you should declare an inner class called Meta
, which has a single field url_template
. This should be the URL template used when getting, creating or updating objects of this type (see the above mentioned examples).
For each field in the Kubernetes documentation, add a field to the class named exactly the same (including case). If the name is an invalid python identifier, add a _
suffix (so exec
becomes exec_
). The value of the field should be an instance of a subclass of Field
, depending on the semantics of the field.
Use this class… |
…when |
---|---|
the field is a list (aka array) |
|
the field can only be set on new objects |
|
the field is required |
|
the field is set by the API server |
|
none of the above applies |
The Field
class takes three parameters:
- type
The type of value this field contains. Can be simple types (int, bool etc),
datetime.datetime
or subclasses ofModel
.- default_value
The field is set to this value when an instance of the class is created. The default default is
None
.- alt_type
The Kubernetes API will in some cases accept two types for a field (usually integer and string). This is the less common of the two, otherwise it has the same meaning as
type
.This parameter is not available for the
ListField
, but so far we have not come across any case where it is needed.
Once you have created a class for your API type, some of the fields will refer to new types which have yet to be defined. Make sure to use existing types defined elsewhere (possibly moving them to k8s.models.common
if they are used in multiple places. Continue defining new subclasses of Model
for each type needed, until you have created all the types required for your API type to be completely specified.
Note
If the Kubernetes documentation says the type is object
, the python type should be dict
.
If the Kubernetes documentation says the type is string
, the python type should be str
.
Most other simple types are obvious.
1# Unless required by applicable law or agreed to in writing, software
2# distributed under the License is distributed on an "AS IS" BASIS,
3# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4# See the License for the specific language governing permissions and
5# limitations under the License.
6
7
8from .common import ObjectMeta
9from ..base import Model
10from ..fields import Field, RequiredField
11
12
13class CrossVersionObjectReference(Model):
14 kind = RequiredField(str)
15 name = RequiredField(str)
16 apiVersion = Field(str)
17
18
19class HorizontalPodAutoscalerSpec(Model):
20 scaleTargetRef = RequiredField(CrossVersionObjectReference)
21 minReplicas = Field(int, 2)
22 maxReplicas = RequiredField(int)
23 targetCPUUtilizationPercentage = Field(int, 50)
24
25
26class HorizontalPodAutoscaler(Model):
27 class Meta:
28 url_template = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}"
29
30 metadata = Field(ObjectMeta)
31 spec = Field(HorizontalPodAutoscalerSpec)
Releasing a new version¶
To make a new release there are a couple steps to follow. Ideally, we want to release from master, as often as possible. Version numbers should adhere to SemVer. When you have a passing build that you want to make a release from, do the following steps: