mirror of https://github.com/knative/func.git
feat: add OpenShift related Annotations & Labels (#1106)
* feat: add OpenShift related Annotations & Labels Signed-off-by: Zbynek Roubalik <zroubalik@gmail.com> * fix test Signed-off-by: Zbynek Roubalik <zroubalik@gmail.com>
This commit is contained in:
parent
f4537dd3d5
commit
b4b4cc34c3
|
|
@ -205,7 +205,7 @@ func TestRemoteRepositories(t *testing.T) {
|
|||
func newClient(verbose bool) *fn.Client {
|
||||
builder := buildpacks.NewBuilder(buildpacks.WithVerbose(verbose))
|
||||
pusher := docker.NewPusher(docker.WithVerbose(verbose))
|
||||
deployer := knative.NewDeployer(DefaultNamespace, verbose)
|
||||
deployer := knative.NewDeployer(knative.WithDeployerNamespace(DefaultNamespace), knative.WithDeployerVerbose(verbose))
|
||||
remover := knative.NewRemover(DefaultNamespace, verbose)
|
||||
lister := knative.NewLister(DefaultNamespace, verbose)
|
||||
|
||||
|
|
|
|||
|
|
@ -61,10 +61,12 @@ func NewClientFactory(n func() *fn.Client) ClientFactory {
|
|||
// defer done()
|
||||
func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
var (
|
||||
p = progress.New(cfg.Verbose) // updates the CLI
|
||||
t = newTransport() // may provide a custom impl which proxies
|
||||
c = newCredentialsProvider(t) // for accessing registries
|
||||
o = []fn.Option{ // standard (shared) options for all commands
|
||||
p = progress.New(cfg.Verbose) // updates the CLI
|
||||
t = newTransport() // may provide a custom impl which proxies
|
||||
c = newCredentialsProvider(t) // for accessing registries
|
||||
d = newKnativeDeployer(cfg.Namespace, cfg.Verbose)
|
||||
pp = newTektonPipelinesProvider(cfg.Namespace, p, c, cfg.Verbose)
|
||||
o = []fn.Option{ // standard (shared) options for all commands
|
||||
fn.WithVerbose(cfg.Verbose),
|
||||
fn.WithProgressListener(p),
|
||||
fn.WithTransport(t),
|
||||
|
|
@ -73,12 +75,8 @@ func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
|||
fn.WithDescriber(knative.NewDescriber(cfg.Namespace, cfg.Verbose)),
|
||||
fn.WithLister(knative.NewLister(cfg.Namespace, cfg.Verbose)),
|
||||
fn.WithRunner(docker.NewRunner(cfg.Verbose)),
|
||||
fn.WithDeployer(knative.NewDeployer(cfg.Namespace, cfg.Verbose)),
|
||||
fn.WithPipelinesProvider(tekton.NewPipelinesProvider(
|
||||
tekton.WithNamespace(cfg.Namespace),
|
||||
tekton.WithProgressListener(p),
|
||||
tekton.WithCredentialsProvider(c),
|
||||
tekton.WithVerbose(cfg.Verbose))),
|
||||
fn.WithDeployer(d),
|
||||
fn.WithPipelinesProvider(pp),
|
||||
fn.WithPusher(docker.NewPusher(
|
||||
docker.WithCredentialsProvider(c),
|
||||
docker.WithProgressListener(p),
|
||||
|
|
@ -132,6 +130,35 @@ func newCredentialsProvider(t http.RoundTripper) docker.CredentialsProvider {
|
|||
return creds.NewCredentialsProvider(options...)
|
||||
}
|
||||
|
||||
func newTektonPipelinesProvider(namespace string, progress *progress.Bar, creds docker.CredentialsProvider, verbose bool) *tekton.PipelinesProvider {
|
||||
options := []tekton.Opt{
|
||||
tekton.WithNamespace(namespace),
|
||||
tekton.WithProgressListener(progress),
|
||||
tekton.WithCredentialsProvider(creds),
|
||||
tekton.WithVerbose(verbose),
|
||||
}
|
||||
|
||||
if openshift.IsOpenShift() {
|
||||
options = append(options, tekton.WithPipelineDecorator(openshift.OpenshiftMetadataDecorator{}))
|
||||
}
|
||||
|
||||
return tekton.NewPipelinesProvider(options...)
|
||||
|
||||
}
|
||||
|
||||
func newKnativeDeployer(namespace string, verbose bool) fn.Deployer {
|
||||
options := []knative.DeployerOpt{
|
||||
knative.WithDeployerNamespace(namespace),
|
||||
knative.WithDeployerVerbose(verbose),
|
||||
}
|
||||
|
||||
if openshift.IsOpenShift() {
|
||||
options = append(options, knative.WithDeployerDecorator(openshift.OpenshiftMetadataDecorator{}))
|
||||
}
|
||||
|
||||
return knative.NewDeployer(options...)
|
||||
}
|
||||
|
||||
func GetDefaultRegistry() string {
|
||||
switch {
|
||||
case openshift.IsOpenShift():
|
||||
|
|
|
|||
|
|
@ -28,18 +28,48 @@ import (
|
|||
const LIVENESS_ENDPOINT = "/health/liveness"
|
||||
const READINESS_ENDPOINT = "/health/readiness"
|
||||
|
||||
type DeployDecorator interface {
|
||||
UpdateAnnotations(fn.Function, map[string]string) map[string]string
|
||||
UpdateLabels(fn.Function, map[string]string) map[string]string
|
||||
}
|
||||
|
||||
type DeployerOpt func(*Deployer)
|
||||
|
||||
type Deployer struct {
|
||||
// Namespace with which to override that set on the default configuration (such as the ~/.kube/config).
|
||||
// If left blank, deployment will commence to the configured namespace.
|
||||
Namespace string
|
||||
// verbose logging enablement flag.
|
||||
verbose bool
|
||||
|
||||
decorator DeployDecorator
|
||||
}
|
||||
|
||||
func NewDeployer(namespaceOverride string, verbose bool) *Deployer {
|
||||
return &Deployer{
|
||||
Namespace: namespaceOverride,
|
||||
verbose: verbose,
|
||||
func NewDeployer(opts ...DeployerOpt) *Deployer {
|
||||
d := &Deployer{}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(d)
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func WithDeployerNamespace(namespace string) DeployerOpt {
|
||||
return func(d *Deployer) {
|
||||
d.Namespace = namespace
|
||||
}
|
||||
}
|
||||
|
||||
func WithDeployerVerbose(verbose bool) DeployerOpt {
|
||||
return func(d *Deployer) {
|
||||
d.verbose = verbose
|
||||
}
|
||||
}
|
||||
|
||||
func WithDeployerDecorator(decorator DeployDecorator) DeployerOpt {
|
||||
return func(d *Deployer) {
|
||||
d.decorator = decorator
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +124,7 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResu
|
|||
referencedSecrets := sets.NewString()
|
||||
referencedConfigMaps := sets.NewString()
|
||||
|
||||
service, err := generateNewService(f)
|
||||
service, err := generateNewService(f, d.decorator)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("knative deployer failed to generate the Knative Service: %v", err)
|
||||
return fn.DeploymentResult{}, err
|
||||
|
|
@ -195,7 +225,7 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResu
|
|||
return fn.DeploymentResult{}, err
|
||||
}
|
||||
|
||||
_, err = client.UpdateServiceWithRetry(ctx, f.Name, updateService(f, newEnv, newEnvFrom, newVolumes, newVolumeMounts), 3)
|
||||
_, err = client.UpdateServiceWithRetry(ctx, f.Name, updateService(f, newEnv, newEnvFrom, newVolumes, newVolumeMounts, d.decorator), 3)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("knative deployer failed to update the Knative Service: %v", err)
|
||||
return fn.DeploymentResult{}, err
|
||||
|
|
@ -240,7 +270,7 @@ func setHealthEndpoints(f fn.Function, c *corev1.Container) *corev1.Container {
|
|||
return c
|
||||
}
|
||||
|
||||
func generateNewService(f fn.Function) (*v1.Service, error) {
|
||||
func generateNewService(f fn.Function, decorator DeployDecorator) (*v1.Service, error) {
|
||||
container := corev1.Container{
|
||||
Image: f.ImageWithDigest(),
|
||||
}
|
||||
|
|
@ -262,16 +292,21 @@ func generateNewService(f fn.Function) (*v1.Service, error) {
|
|||
}
|
||||
container.VolumeMounts = newVolumeMounts
|
||||
|
||||
labels, err := processLabels(f)
|
||||
labels, err := processLabels(f, decorator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
annotations := f.Annotations
|
||||
if decorator != nil {
|
||||
annotations = decorator.UpdateAnnotations(f, annotations)
|
||||
}
|
||||
|
||||
service := &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: f.Name,
|
||||
Labels: labels,
|
||||
Annotations: f.Annotations,
|
||||
Annotations: annotations,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
ConfigurationSpec: v1.ConfigurationSpec{
|
||||
|
|
@ -297,7 +332,7 @@ func generateNewService(f fn.Function) (*v1.Service, error) {
|
|||
return service, nil
|
||||
}
|
||||
|
||||
func updateService(f fn.Function, newEnv []corev1.EnvVar, newEnvFrom []corev1.EnvFromSource, newVolumes []corev1.Volume, newVolumeMounts []corev1.VolumeMount) func(service *v1.Service) (*v1.Service, error) {
|
||||
func updateService(f fn.Function, newEnv []corev1.EnvVar, newEnvFrom []corev1.EnvFromSource, newVolumes []corev1.Volume, newVolumeMounts []corev1.VolumeMount, decorator DeployDecorator) func(service *v1.Service) (*v1.Service, error) {
|
||||
return func(service *v1.Service) (*v1.Service, error) {
|
||||
// Removing the name so the k8s server can fill it in with generated name,
|
||||
// this prevents conflicts in Revision name when updating the KService from multiple places.
|
||||
|
|
@ -305,6 +340,10 @@ func updateService(f fn.Function, newEnv []corev1.EnvVar, newEnvFrom []corev1.En
|
|||
|
||||
// Don't bother being as clever as we are with env variables
|
||||
// Just set the annotations and labels to be whatever we find in func.yaml
|
||||
if decorator != nil {
|
||||
service.ObjectMeta.Annotations = decorator.UpdateAnnotations(f, service.ObjectMeta.Annotations)
|
||||
}
|
||||
|
||||
for k, v := range f.Annotations {
|
||||
service.ObjectMeta.Annotations[k] = v
|
||||
}
|
||||
|
|
@ -328,7 +367,7 @@ func updateService(f fn.Function, newEnv []corev1.EnvVar, newEnvFrom []corev1.En
|
|||
return service, err
|
||||
}
|
||||
|
||||
labels, err := processLabels(f)
|
||||
labels, err := processLabels(f, decorator)
|
||||
if err != nil {
|
||||
return service, err
|
||||
}
|
||||
|
|
@ -354,7 +393,7 @@ func updateService(f fn.Function, newEnv []corev1.EnvVar, newEnvFrom []corev1.En
|
|||
// value: value1
|
||||
// - key: EXAMPLE2 # Label from the local ENV var
|
||||
// value: {{ env:MY_ENV }}
|
||||
func processLabels(f fn.Function) (map[string]string, error) {
|
||||
func processLabels(f fn.Function, decorator DeployDecorator) (map[string]string, error) {
|
||||
labels := map[string]string{
|
||||
labels.FunctionKey: labels.FunctionValue,
|
||||
labels.FunctionNameKey: f.Name,
|
||||
|
|
@ -365,6 +404,11 @@ func processLabels(f fn.Function) (map[string]string, error) {
|
|||
labels.DeprecatedFunctionRuntimeKey: f.Runtime,
|
||||
// --- end of handling usage of deprecated runtime labels
|
||||
}
|
||||
|
||||
if decorator != nil {
|
||||
labels = decorator.UpdateLabels(f, labels)
|
||||
}
|
||||
|
||||
for _, label := range f.Labels {
|
||||
if label.Key != nil && label.Value != nil {
|
||||
if strings.HasPrefix(*label.Value, "{{") {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package openshift
|
||||
|
||||
import (
|
||||
fn "knative.dev/kn-plugin-func"
|
||||
)
|
||||
|
||||
const (
|
||||
AnnotationOpenShiftVcsUri = "app.openshift.io/vcs-uri"
|
||||
AnnotationOpenShiftVcsRef = "app.openshift.io/vcs-ref"
|
||||
|
||||
LabelAppK8sInstance = "app.kubernetes.io/instance"
|
||||
)
|
||||
|
||||
type OpenshiftMetadataDecorator struct{}
|
||||
|
||||
func (o OpenshiftMetadataDecorator) UpdateAnnotations(f fn.Function, annotations map[string]string) map[string]string {
|
||||
if annotations == nil {
|
||||
annotations = map[string]string{}
|
||||
}
|
||||
if f.Git.URL != nil {
|
||||
annotations[AnnotationOpenShiftVcsUri] = *f.Git.URL
|
||||
}
|
||||
if f.Git.Revision != nil {
|
||||
annotations[AnnotationOpenShiftVcsRef] = *f.Git.Revision
|
||||
}
|
||||
|
||||
return annotations
|
||||
}
|
||||
|
||||
func (o OpenshiftMetadataDecorator) UpdateLabels(f fn.Function, labels map[string]string) map[string]string {
|
||||
if labels == nil {
|
||||
labels = map[string]string{}
|
||||
}
|
||||
|
||||
labels[LabelAppK8sInstance] = f.Name
|
||||
|
||||
return labels
|
||||
}
|
||||
|
|
@ -24,6 +24,10 @@ import (
|
|||
"knative.dev/pkg/apis"
|
||||
)
|
||||
|
||||
type PipelineDecorator interface {
|
||||
UpdateLabels(fn.Function, map[string]string) map[string]string
|
||||
}
|
||||
|
||||
type Opt func(*PipelinesProvider)
|
||||
|
||||
type PipelinesProvider struct {
|
||||
|
|
@ -33,6 +37,7 @@ type PipelinesProvider struct {
|
|||
verbose bool
|
||||
progressListener fn.ProgressListener
|
||||
credentialsProvider docker.CredentialsProvider
|
||||
decorator PipelineDecorator
|
||||
}
|
||||
|
||||
func WithNamespace(namespace string) Opt {
|
||||
|
|
@ -59,6 +64,12 @@ func WithVerbose(verbose bool) Opt {
|
|||
}
|
||||
}
|
||||
|
||||
func WithPipelineDecorator(decorator PipelineDecorator) Opt {
|
||||
return func(pp *PipelinesProvider) {
|
||||
pp.decorator = decorator
|
||||
}
|
||||
}
|
||||
|
||||
func NewPipelinesProvider(opts ...Opt) *PipelinesProvider {
|
||||
pp := &PipelinesProvider{}
|
||||
|
||||
|
|
@ -87,6 +98,9 @@ func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) error {
|
|||
|
||||
// let's specify labels that will be applied to every resouce that is created for a Pipeline
|
||||
labels := map[string]string{labels.FunctionNameKey: f.Name}
|
||||
if pp.decorator != nil {
|
||||
labels = pp.decorator.UpdateLabels(f, labels)
|
||||
}
|
||||
|
||||
err = k8s.CreatePersistentVolumeClaim(ctx, getPipelinePvcName(f), pp.namespace, labels, corev1.ReadWriteOnce, *resource.NewQuantity(DefaultPersistentVolumeClaimSize, resource.DecimalSI))
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue