Skip to content

Commit

Permalink
Create CRD for Function objects (#3675)
Browse files Browse the repository at this point in the history
* Create Function CRD in configapi

The definition is broadly copied from the aggregated apiserver.

* Generated output for Function CRD

* Implement controller for function discovery

* functiondiscovery controller: add test for discovery

* Simple mock OCI server

* functiondiscovery: poll for functions every 15 minutes

Until we can do something better, we poll every 15 minutes (with a bit
of jitter to avoid synchronization)

* Add functiondiscovery to default reconcilers
  • Loading branch information
justinsb committed Dec 6, 2022
1 parent 4952e6c commit 8e9f29e
Show file tree
Hide file tree
Showing 30 changed files with 2,435 additions and 30 deletions.
4 changes: 2 additions & 2 deletions porch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ TEST_GIT_SERVER_IMAGE ?= test-git-server
# Only enable a subset of reconcilers in porch controllers by default. Use the RECONCILERS
# env variable to specify a specific list of reconcilers or use
# RECONCILERS=* to enable all known reconcilers.
ALL_RECONCILERS="rootsyncsets,remoterootsyncsets,workloadidentitybindings,rootsyncdeployments"
ALL_RECONCILERS="rootsyncsets,remoterootsyncsets,workloadidentitybindings,rootsyncdeployments,functiondiscovery"
ifndef RECONCILERS
ENABLED_RECONCILERS="rootsyncsets,remoterootsyncsets,workloadidentitybindings"
ENABLED_RECONCILERS="rootsyncsets,remoterootsyncsets,workloadidentitybindings,functiondiscovery"
else
ifeq ($(RECONCILERS),*)
ENABLED_RECONCILERS=${ALL_RECONCILERS}
Expand Down
135 changes: 135 additions & 0 deletions porch/api/porchconfig/v1alpha1/config.porch.kpt.dev_functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: functions.config.porch.kpt.dev
spec:
group: config.porch.kpt.dev
names:
kind: Function
listKind: FunctionList
plural: functions
singular: function
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: Function represents a kpt function discovered in a repository
Function resources are created automatically by discovery in a registered
Repository. Function resource names will be computed as <Repository Name>:<Function
Name> to ensure uniqueness of names, and will follow formatting of [DNS
Subdomain Names](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names).
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: FunctionSpec defines the desired state of a Function
properties:
description:
description: Description is a short description of the function.
type: string
documentationUrl:
description: '`DocumentationUrl specifies the URL of comprehensive
function documentation`'
type: string
functionConfigs:
items:
description: FunctionConfig specifies all the valid types of the
function config for this function. If unspecified, defaults to
v1/ConfigMap. For example, function `set-namespace` accepts both
`ConfigMap` and `SetNamespace`
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this
representation of an object. Servers should convert recognized
schemas to the latest internal value, and may reject unrecognized
values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource
this object represents. Servers may infer this from the endpoint
the client submits requests to. Cannot be updated. In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
requiredFields:
description: 'Experimental: requiredFields tells necessary fields
and is aimed to help users write the FunctionConfig. Otherwise,
users can get the required fields info from the function evaluation
error message.'
items:
type: string
type: array
type: object
type: array
functionTypes:
description: FunctionType specifies the function types (mutator, validator
or/and others).
items:
type: string
type: array
image:
description: Image specifies the function image, such as 'gcr.io/kpt-fn/gatekeeper:v0.2'.
type: string
keywords:
description: Keywords are used as filters to provide correlation in
function discovery.
items:
type: string
type: array
repositoryRef:
description: RepositoryRef references the repository in which the
function is located.
properties:
name:
description: Name of the Repository resource referenced.
type: string
required:
- name
type: object
required:
- description
- image
- repositoryRef
type: object
status:
description: FunctionStatus defines the observed state of Function
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
32 changes: 22 additions & 10 deletions porch/api/porchconfig/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,43 @@ var (

// We removed SchemeBuilder to keep our dependencies small

KindRepository = KindInfo{
TypeRepository = TypeInfo{
Kind: "Repository",
Resource: GroupVersion.WithResource("repositories"),
objects: []runtime.Object{&Repository{}, &RepositoryList{}},
}

RepositoryGVK = schema.GroupVersionKind{
Group: GroupVersion.Group,
Version: GroupVersion.Version,
Kind: "Repository",
TypeFunction = TypeInfo{
Kind: "Function",
Resource: GroupVersion.WithResource("functions"),
objects: []runtime.Object{&Function{}, &FunctionList{}},
}

AllKinds = []KindInfo{KindRepository}
AllKinds = []TypeInfo{TypeRepository, TypeFunction}
)

//+kubebuilder:object:generate=false

// KindInfo holds type meta-information
type KindInfo struct {
// TypeInfo holds type meta-information
type TypeInfo struct {
Kind string
Resource schema.GroupVersionResource
objects []runtime.Object
}

// GVK returns the schema.GroupVersionKind for the type
func (t *TypeInfo) GVK() schema.GroupVersionKind {
return t.Resource.GroupVersion().WithKind(t.Kind)
}

// APIVersion returns the apiVersion for the type
func (t *TypeInfo) APIVersion() string {
return t.Resource.GroupVersion().Identifier()
}

// GroupResource returns the GroupResource for the kind
func (k *KindInfo) GroupResource() schema.GroupResource {
return k.Resource.GroupResource()
func (t *TypeInfo) GroupResource() schema.GroupResource {
return t.Resource.GroupResource()
}

func AddToScheme(scheme *runtime.Scheme) error {
Expand Down
107 changes: 107 additions & 0 deletions porch/api/porchconfig/v1alpha1/types_functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1alpha1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:path=functions,singular=function

// Function represents a kpt function discovered in a repository
// Function resources are created automatically by discovery in a registered Repository.
// Function resource names will be computed as <Repository Name>:<Function Name>
// to ensure uniqueness of names, and will follow formatting of
// [DNS Subdomain Names](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names).
type Function struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec FunctionSpec `json:"spec,omitempty"`
Status FunctionStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// FunctionList
type FunctionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`

Items []Function `json:"items"`
}

type FunctionType string

const (
FunctionTypeValidator FunctionType = "validator"
FunctionTypeMutator FunctionType = "mutator"
)

// FunctionSpec defines the desired state of a Function
type FunctionSpec struct {
// Image specifies the function image, such as 'gcr.io/kpt-fn/gatekeeper:v0.2'.
Image string `json:"image"`

// RepositoryRef references the repository in which the function is located.
RepositoryRef RepositoryRef `json:"repositoryRef"`

// FunctionType specifies the function types (mutator, validator or/and others).
FunctionTypes []FunctionType `json:"functionTypes,omitempty"`

FunctionConfigs []FunctionConfig `json:"functionConfigs,omitempty"`

// Keywords are used as filters to provide correlation in function discovery.
Keywords []string `json:"keywords,omitempty"`

// Description is a short description of the function.
Description string `json:"description"`

// `DocumentationUrl specifies the URL of comprehensive function documentation`
DocumentationUrl string `json:"documentationUrl,omitempty"`

// InputTypes specifies to which input KRM types the function applies. Specified as Group Version Kind.
// For example:
//
// inputTypes:
// - kind: RoleBinding
// # If version is unspecified, applies to all versions
// apiVersion: rbac.authorization.k8s.io
// - kind: ClusterRoleBinding
// apiVersion: rbac.authorization.k8s.io/v1
// InputTypes []metav1.TypeMeta

// OutputTypes specifies types of any KRM resources the function creates
// For example:
//
// outputTypes:
// - kind: ConfigMap
// apiVersion: v1
// OutputTypes []metav1.TypeMeta

}

// FunctionConfig specifies all the valid types of the function config for this function.
// If unspecified, defaults to v1/ConfigMap. For example, function `set-namespace` accepts both `ConfigMap` and `SetNamespace`
type FunctionConfig struct {
metav1.TypeMeta `json:",inline"`
// Experimental: requiredFields tells necessary fields and is aimed to help users write the FunctionConfig.
// Otherwise, users can get the required fields info from the function evaluation error message.
RequiredFields []string `json:"requiredFields,omitempty"`
}

// FunctionStatus defines the observed state of Function
type FunctionStatus struct {
}

0 comments on commit 8e9f29e

Please sign in to comment.