Skip to content

Commit 5103331

Browse files
committed
CLEANUP/MINOR: crd: clean crs documentation
1 parent 610d0b0 commit 5103331

File tree

2 files changed

+44
-123
lines changed

2 files changed

+44
-123
lines changed

crs/README.md

+44-90
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
# Custom Resources
22

33
## Purpose
4+
45
This document aims to provide basic understanding of the workflow of writing a new custom resource for HAProxy Ingress Controller.
56
Custom resources should be derived, whenever possible, from the [HAProxy CN (Client Native)](https://github.com/haproxytech/client-native) by reusing [HAProxy Models](https://github.com/haproxytech/client-native#haproxy-models).
67
This guide describes how to create a CR (Custom Resource) to configure the global HAProxy section.
78

89
## Prerequisites
9-
We suppose that an HAProxy CN Model, corresponding to the kubernetes custom resource, is already available. This is the case for the HAProxy global section, that we are dealing with in this guide, where we are going to reuse the following [global model](https://github.com/haproxytech/client-native/blob/master/models/global.go).
10+
11+
We suppose that an HAProxy CN Model, corresponding to the kubernetes custom resource, is already available. This is the case for the HAProxy global section, that we are dealing with in this guide.
1012
If it is not the case, this needs to be done in [HAProxy Native client](https://github.com/haproxytech/client-native) by providing [swagger specification](https://github.com/haproxytech/client-native/blob/master/specification/build/haproxy_spec.yaml) of the Model and generate it via [make models](https://github.com/haproxytech/client-native/blob/master/Makefile).
1113

1214
## Directory Layout
1315

14-
```
16+
```txt
1517
crs
1618
├── api
17-
│   └── core
18-
│   └── v1alpha1
19+
│   └── ingress
20+
│   └── v1
1921
2022
├── definition
2123
│   └── global.yaml
@@ -28,154 +30,106 @@ crs
2830
├── code-generator.sh
2931
└── README.md
3032
```
33+
3134
- **crs/definition/**: Directory for Custom Resource Definition
3235
- **crs/api/<group>/<version>/**: GoLang Types should be created in the directory corresponding to their API Group and Version.
33-
- **crs/code-generator.sh**: script using Kubernetes code generators to build native, versioned clients, informers and other helpers.
34-
- **crs/generated**: code generated automatically via "code-generator.sh".
35-
36-
## Custom Resource Creation
37-
### CRD
38-
Let's start by creating the Custom Resource Definition describing the Global CR and defining the kind `Global` in the API Group `core.haproxy.org`
39-
To follow the above directory layout convention, the Global CRD should be in *crs/definitions/core/global.yaml*
40-
The following is the beginning of the CRD, full content can be found in the corresponding yaml file:
41-
```
42-
apiVersion: apiextensions.k8s.io/v1
43-
kind: CustomResourceDefinition
44-
metadata:
45-
name: globals.core.haproxy.org
46-
spec:
47-
group: core.haproxy.org
48-
names:
49-
kind: Global
50-
plural: globals
51-
scope: Namespaced
52-
versions:
53-
- name: v1alpha1
54-
served: true
55-
storage: true
56-
schema:
57-
openAPIV3Schema:
58-
type: object
59-
properties:
60-
spec:
61-
type: object
62-
required:
63-
- config
64-
properties:
65-
config:
66-
title: Global
67-
description: HAProxy global configuration
68-
type: object
69-
properties:
70-
chroot:
71-
type: string
72-
pattern: '^[^\s]+$'
73-
group:
74-
type: string
75-
pattern: '^[^\s]+$'
76-
hard_stop_after:
77-
type: integer
78-
user:
79-
type: string
80-
pattern: '^[^\s]+$'
81-
daemon:
82-
type: string
83-
enum: [enabled, disabled]
84-
```
85-
The CRD is created via `apiextensions.k8s.io/v1` where the definition of a [structural schema](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation) is mandatory and used for OpenAPI v3.0 validation.
86-
The Custom Resource Definition is constructed by providing:
87-
- API Group Name: `core.haproxy.org`, this is the group where you can find custom resources related to HAProxy configuration.
88-
- Kind Name of the Resource: `Global` (and `globals` for plural name)
89-
- Resource Scope: in this case it is `Namespaced`
90-
- Group Version: `v1alpha1`
91-
- openAPIV3Schema: For schema validation you just copy the [global schema](https://github.com/haproxytech/client-native/blob/master/specification/models/configuration.yaml#L2) from Client Native repository and insert it in the `config` field of the CRD.
92-
**NB:** a helper script is available under `crs/get-crd-schema.sh` in order to automatically retreive the schema from the CN repository. The script takes the name of Client Native model as parameter (ex: `get-crd-schema.sh global`) and returns to stdout the schema after applying the necessary changes to make it a [valid schema](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation) for kubernetes.
36+
- **crs/generated**: code generated automatically via `make cr_generate`.
9337

9438
### GoLang Type
95-
In this guide the API group is `core.haproxy.org` (this group is used for any resource dealing with haproxy configuration) and the API version is `alpha1v1`.
96-
So to follow the */crs/api/<group>/<version>/* convention, the GoLang Type describing the `Global` CR should be in *crs/api/core/alpha1v1/global.go* with the following content:
97-
```
98-
package v1alpha1
39+
40+
In this guide the API group is `ingress.v1.haproxy.org` (this group is used for any resource dealing with haproxy configuration) and the API version is `v1`.
41+
So to follow the */crs/api/<group>/<version>/* convention, the GoLang Type describing the `Global` CR should be in *crs/api/ingress/v1/global.go* with the following content:
42+
43+
```go
44+
package v1
9945

10046
import (
101-
"github.com/haproxytech/client-native/v3/models"
102-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
47+
"github.com/haproxytech/client-native/v5/models"
48+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10349
)
10450

10551
// +genclient
10652
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
10753

10854
// Global is a specification for a Global resource
10955
type Global struct {
110-
metav1.TypeMeta `json:",inline"`
111-
metav1.ObjectMeta `json:"metadata,omitempty"`
56+
metav1.TypeMeta `json:",inline"`
57+
metav1.ObjectMeta `json:"metadata,omitempty"`
11258

113-
Spec GlobalSpec `json:"spec"`
59+
Spec GlobalSpec `json:"spec"`
11460
}
11561

11662
// GlobalSpec defines the desired state of Global
11763
type GlobalSpec struct {
118-
Config *models.Global `json:"config"`
64+
Config *models.Global `json:"config"`
11965
}
12066

12167
// DeepCopyInto deepcopying the GlobalSpec receiver into out. in must be non nil.
12268
func (in *GlobalSpec) DeepCopyInto(out *GlobalSpec) {
123-
*out = *in
124-
if in.Config != nil {
125-
b, _ := in.Config.MarshalBinary()
126-
_ = out.Config.UnmarshalBinary(b)
127-
}
69+
*out = *in
70+
if in.Config != nil {
71+
b, _ := in.Config.MarshalBinary()
72+
_ = out.Config.UnmarshalBinary(b)
73+
}
12874
}
12975

13076
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
13177

13278
// GlobalList is a list of Global resources
13379
type GlobalList struct {
134-
metav1.TypeMeta `json:",inline"`
135-
metav1.ListMeta `json:"metadata"`
80+
metav1.TypeMeta `json:",inline"`
81+
metav1.ListMeta `json:"metadata"`
13682

137-
Items []Global `json:"items"`
83+
Items []Global `json:"items"`
13884
}
13985
```
86+
14087
- The GoLang types (Global for a specific resource and GlobalList for a list of resources) need to embed `TypeMeta` and `ObjectMeta` as they are mandatory for the Kubernetes type system and any resource served by Kubernetes API.
14188
- The Spec reuses the [global configuration](https://github.com/haproxytech/client-native/blob/master/models/global.go) from HAProxy CN Models via the CR `config` field.
14289
- Additional fields can added later to Spec if need be, but any input related to the HAProxy Global section config is provided via the `config` field.
14390
- The deepcopy-gen tags are used to automatically generate deepCopy methods, required for any Kubernetes object, via the [code-generator](https://github.com/kubernetes/code-generator) tool. However Code Generators cannot generate the deepCopy method for types in external packages (in this case "github.com/haproxytech/client-native/v3/models") so this needs to be done manually by relying on the `MarshalBinary` and `UnmarshalBinary` of HAProxy Models.
14491

14592
### Code Generation
93+
14694
Custom Resources require more code and methods in order to be served by Kubernetes API but fortunately most of it can be generated automatically by Kubernetes code generators.
14795
The tool we are using is [k8s.io/code-generator](https://github.com/kubernetes/code-generator) which comes with the following code generators for CRs:
96+
14897
- deepcopy-gen: generates the new Type's DeepCopy methods.
14998
- register-gen: generates methods to register the new Type in [Kubernetes scheme](https://github.com/kubernetes/apimachinery/blob/ef51ab160544f9d05b68e132a4af0b0fab459954/pkg/runtime/scheme.go#L47) and make it known to the Kubernetes type system.
15099
- client-gen: generates the client set that will give us access to the new CR
151100
- informer-gen: generates informer methods in order to watch and react to the CR changes.
152101
- lister-gen: generates lister methods which provide a read-only caching layer for GET and LIST requests.
153102

154103
Before generating code, some global tags need to be set in the package of the versioned API group which should be in *crs/api/<group>/<version>/* directory.
155-
Usually this goes into the package's doc.go, so in this case it would be in *crs/api/core/alpha1v1/doc.go* with the following content:
156-
```
157-
// Package v1alpha1 contains the core v1alpha1 API group
104+
Usually this goes into the package's doc.go, so in this case it would be in *crs/api/ingress/v1/doc.go* with the following content:
105+
106+
```yml
107+
// Package v1 contains the core v1 API group
158108
//
159109
// +k8s:deepcopy-gen=package
160-
// +groupName=core.haproxy.org
161-
package v1alpha1
110+
// +groupName=ingress.v1.haproxy.org
111+
package v1
162112
```
163-
In addition to including a number of global code generation tags, "doc.go" is used to describe the API group's purpose.
164113

165-
Now you can generate all necessary code for all CRs under the */crs/api* directory, via `make cr_generate` which calls the script `crs/code-generators.sh`
114+
In addition to including a number of global code generation tags, "doc.go" is used to describe the API group's purpose.
166115

116+
Now you can generate all necessary code for all CRs under the */crs/api* directory, via `make cr_generate`
167117

168118
## Custom Resource Management
119+
169120
A custom resource manager already [exists](../controller/crmanager.go) as a single entry point for any custom resource defined inside HAProxy Ingress Controller.
170121
Its role is to be the unique delegate for all CR related task via the following CR interface:
171-
```
122+
123+
```go
172124
type CR interface {
173125
GetKind() string
174126
GetInformer(chan SyncDataEvent, informers.SharedInformerFactory) cache.SharedIndexInformer
175127
ProcessEvent(*store.K8s, SyncDataEvent) bool
176128
}
177129
```
130+
178131
Each CR should implement the above interface in order to:
132+
179133
- provide the CR kind which allows the CRManager to register supported Kinds and map them to the corresponding CR implementation.
180134
- provide the Kubernetes Informer to watch and react to CR events.
181135
- Process the CR events which is mainly about storing the CR object in the Ingress Controller store.

crs/get-crd-schema.sh

-33
This file was deleted.

0 commit comments

Comments
 (0)