Note: Added in release v0.1-alpha.11
Create the subresource definition using apiserver-boot
To create a subresource of for the resource Group/Version/Kind run the following command from the root directory (e.g. the one that containings glide.yaml)
apiserver-boot create subresource --subresource <subresource> --group <resource-group> --version <resource-version> --kind <resource-kind>
This will:
- create
pkg/apis/<group>/<version>/<subresource>_<kind>_types.go
- contains the rest implementation
- create
pkg/apis/<group>/<version>/<subresource>_<kind>_types_test.go
- contains a simple test to invoke the subresource and make sure it returns 200
- update
pkg/apis/<group>/<version>/<kind>_types.go
- add the subresource comment directive to the resource
Next regenerate the generated code to wire up the subresource
apiserver-boot build generated
Run the tests
go test ./pkg/...
Look for the subresource endpoint through the discovery service:
# shell #1
apiserver-boot run local
# shell #2
kubectl --kubeconfig kubeconfig proxy
# shell #3
curl 127.0.0.1:8001/
curl 127.0.0.1:8001/apis/<group>.<domain>/<version>
Create the subresource definition by hand
Create a resource under pkg/apis/<group>/<version>/<resource>_types.go
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +resource:path=bars
// +subresource:request=Scale,path=scale,rest=ScaleBarREST
type Bar struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec BarSpec `json:"spec,omitempty"`
Status BarStatus `json:"status,omitempty"`
}
The following line tells the code generator to generate a subresource for this resource.
- under the path
bar/scale
- with request Kind
Scale
- implemented by the go type
ScaleBarREST
Scale and ScaleBarREST live in the versioned package (same as the versioned resource definition)
// +subresource:request=Scale,path=scale,rest=ScaleBarREST
Define the request type in the same _types.go file
// +genclient=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +subresource-request
type Scale struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Faculty int `json:"faculty,omitempty"`
}
Note the line:
// +subresource-request
This tells the code generator that this is a subresource type and to register it in the wiring.
Create the rest implementation in the versioned package.
Example:
// +k8s:deepcopy-gen=false
type ScaleBarREST struct {
Registry BarRegistry
}
// Scale Subresource
var _ rest.CreaterUpdater = &ScaleBarREST{}
var _ rest.Patcher = &ScaleBarREST{}
func (r *ScaleBarREST) Create(ctx request.Context, obj runtime.Object) (runtime.Object, error) {
scale := obj.(*Scale)
b, err := r.Registry.GetBar(ctx, scale.Name, &metav1.GetOptions{})
if err != nil {
return nil, err
}
// Do something with b...
// Save the udpated b
r.Registry.UpdateBar(ctx, b)
return u, nil
}
// Get retrieves the object from the storage. It is required to support Patch.
func (r *ScaleBarREST) Get(ctx request.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
return nil, nil
}
// Update alters the status subset of an object.
func (r *ScaleBarREST) Update(ctx request.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
return nil, false, nil
}
func (r *ScaleBarREST) New() runtime.Object {
return &Scale{}
}
Define the struct type implementing the REST api. The Registry field is required, and provides a type safe library to read / write instances of Bar from the storage.
// +k8s:deepcopy-gen=false
type ScaleBarREST struct {
Registry BarRegistry
}
Enforce local compile time checks that the struct implements the needed REST methods
// Scale Subresource
var _ rest.CreaterUpdater = &ScaleBarREST{}
var _ rest.Patcher = &ScaleBarREST{}
Implement create and update methods using the Registry to update the parent resource.
func (r *ScaleBarREST) Create(ctx request.Context, obj runtime.Object) (runtime.Object, error) {
...
}
// Update alters the status subset of an object.
func (r *ScaleBarREST) Update(ctx request.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
...
}
Implement a read method using the Registry to read the parent resource.
// Get retrieves the object from the storage. It is required to support Patch.
func (r *ScaleBarREST) Get(ctx request.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
...
}
Implement a method that creates new instance of the request.
func (r *ScaleBarREST) New() runtime.Object {
return &Scale{}
}
Run the code generation command to generate the wiring for your subresource.
apiserver-boot build generated
Use the RESTClient to call your subresource. Client go is not generated for subresources, so you will need to manually invoke the subresource.
client.RESTClient()
err := restClient.Post().Namespace("default").
Name("name").
Resource("bars").
SubResource("scale").
Body(scale).Do().Error()
...