src: use Knative Client libraries (#167)

Signed-off-by: Zbynek Roubalik <zroubali@redhat.com>
This commit is contained in:
Zbynek Roubalik 2020-10-14 10:42:26 +02:00 committed by GitHub
parent ffc6a123e4
commit 68351bd0ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 120 additions and 156 deletions

View File

@ -42,10 +42,6 @@ overwrite the value in faas.yaml.
func runDelete(cmd *cobra.Command, args []string) (err error) {
config := newDeleteConfig(args).Prompt()
remover := knative.NewRemover(config.Namespace)
remover.Verbose = config.Verbose
remover.Namespace = config.Namespace
function, err := faas.NewFunction(config.Path)
if err != nil {
return
@ -56,6 +52,13 @@ func runDelete(cmd *cobra.Command, args []string) (err error) {
return fmt.Errorf("the given path '%v' does not contain an initialized Function.", config.Path)
}
remover, err := knative.NewRemover(config.Namespace)
if err != nil {
return
}
remover.Verbose = config.Verbose
client := faas.New(
faas.WithVerbose(config.Verbose),
faas.WithRemover(remover))

View File

@ -103,7 +103,6 @@ func runDeploy(cmd *cobra.Command, _ []string) (err error) {
listener := progress.New()
deployer.Verbose = config.Verbose
deployer.Namespace = function.Namespace
client := faas.New(
faas.WithVerbose(config.Verbose),

View File

@ -1,43 +1,68 @@
package knative
import (
"bytes"
"fmt"
"io"
"os"
"time"
"k8s.io/client-go/tools/clientcmd"
"knative.dev/client/pkg/kn/commands"
clienteventingv1beta1 "knative.dev/client/pkg/eventing/v1beta1"
clientservingv1 "knative.dev/client/pkg/serving/v1"
eventingv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1"
servingv1 "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1"
)
const (
DefaultWaitingTimeout = 60 * time.Second
)
func NewClient(namespace string, verbose bool) (clientservingv1.KnServingClient, io.Writer, error) {
func NewServingClient(namespace string) (clientservingv1.KnServingClient, error) {
p := commands.KnParams{}
p.Initialize()
// Capture output in a buffer if verbose is not enabled for output on error.
if verbose {
p.Output = os.Stdout
} else {
p.Output = &bytes.Buffer{}
}
if namespace == "" {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
namespace, _, _ = clientConfig.Namespace()
}
client, err := p.NewServingClient(namespace)
restConfig, err := getClientConfig().ClientConfig()
if err != nil {
return nil, p.Output, fmt.Errorf("failed to create new serving client: %v", err)
return nil, fmt.Errorf("failed to create new serving client: %v", err)
}
return client, p.Output, nil
servingClient, err := servingv1.NewForConfig(restConfig)
if err != nil {
return nil, fmt.Errorf("failed to create new serving client: %v", err)
}
client := clientservingv1.NewKnServingClient(servingClient, namespace)
return client, nil
}
func NewEventingClient(namespace string) (clienteventingv1beta1.KnEventingClient, error) {
restConfig, err := getClientConfig().ClientConfig()
if err != nil {
return nil, fmt.Errorf("failed to create new serving client: %v", err)
}
eventingClient, err := eventingv1beta1.NewForConfig(restConfig)
if err != nil {
return nil, fmt.Errorf("failed to create new eventing client: %v", err)
}
client := clienteventingv1beta1.NewKnEventingClient(eventingClient, namespace)
return client, nil
}
func GetNamespace(defaultNamespace string) (namespace string, err error) {
namespace = defaultNamespace
if defaultNamespace == "" {
namespace, _, err = getClientConfig().Namespace()
if err != nil {
return
}
}
return
}
func getClientConfig() clientcmd.ClientConfig {
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{})
}

View File

@ -1,7 +1,6 @@
package knative
import (
"bytes"
"fmt"
"strings"
"time"
@ -28,12 +27,11 @@ type Deployer struct {
func NewDeployer(namespaceOverride string) (deployer *Deployer, err error) {
deployer = &Deployer{}
_, namespace, err := newClientConfig(namespaceOverride)
namespace, err := GetNamespace(namespaceOverride)
if err != nil {
return
}
deployer.Namespace = namespace
// deployer.client, err = servingv1client.NewForConfig(config)
return
}
@ -41,70 +39,50 @@ func (d *Deployer) Deploy(f faas.Function) (err error) {
// k8s does not support service names with dots. so encode it such that
// www.my-domain,com -> www-my--domain-com
encodedName, err := k8s.ToK8sAllowedName(f.Name)
serviceName, err := k8s.ToK8sAllowedName(f.Name)
if err != nil {
return
}
client, output, err := NewClient(d.Namespace, d.Verbose)
client, err := NewServingClient(d.Namespace)
if err != nil {
return
}
_, err = client.GetService(encodedName)
_, err = client.GetService(serviceName)
if err != nil {
if errors.IsNotFound(err) {
// Let's create a new Service
err := client.CreateService(generateNewService(encodedName, f.Image))
err := client.CreateService(generateNewService(serviceName, f.Image))
if err != nil {
if !d.Verbose {
err = fmt.Errorf("failed to deploy the service: %v.\nStdOut: %s", err, output.(*bytes.Buffer).String())
} else {
err = fmt.Errorf("failed to deploy the service: %v", err)
}
err = fmt.Errorf("knative deployer failed to deploy the service: %v", err)
return err
}
err, _ = client.WaitForService(encodedName, DefaultWaitingTimeout, wait.NoopMessageCallback())
err, _ = client.WaitForService(serviceName, DefaultWaitingTimeout, wait.NoopMessageCallback())
if err != nil {
if !d.Verbose {
err = fmt.Errorf("deployer failed to wait for the service to become ready: %v.\nStdOut: %s", err, output.(*bytes.Buffer).String())
} else {
err = fmt.Errorf("deployer failed to wait for the service to become ready: %v", err)
}
err = fmt.Errorf("knative deployer failed to wait for the service to become ready: %v", err)
return err
}
route, err := client.GetRoute(encodedName)
route, err := client.GetRoute(serviceName)
if err != nil {
if !d.Verbose {
err = fmt.Errorf("deployer failed to get the route: %v.\nStdOut: %s", err, output.(*bytes.Buffer).String())
} else {
err = fmt.Errorf("deployer failed to get the route: %v", err)
}
err = fmt.Errorf("knative deployer failed to get the route: %v", err)
return err
}
fmt.Println("Function deployed on: " + route.Status.URL.String())
} else {
if !d.Verbose {
err = fmt.Errorf("deployer failed to get the service: %v.\nStdOut: %s", err, output.(*bytes.Buffer).String())
} else {
err = fmt.Errorf("deployer failed to get the service: %v", err)
}
err = fmt.Errorf("knative deployer failed to get the service: %v", err)
return err
}
} else {
// Update the existing Service
err = client.UpdateServiceWithRetry(encodedName, updateEnvVars(f.EnvVars), 3)
err = client.UpdateServiceWithRetry(serviceName, updateEnvVars(f.EnvVars), 3)
if err != nil {
if !d.Verbose {
err = fmt.Errorf("deployer failed to update the service: %v.\nStdOut: %s", err, output.(*bytes.Buffer).String())
} else {
err = fmt.Errorf("deployer failed to update the service: %v", err)
}
err = fmt.Errorf("knative deployer failed to update the service: %v", err)
return err
}
}

View File

@ -1,44 +1,27 @@
package knative
import (
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
v1 "knative.dev/client/pkg/serving/v1"
"knative.dev/eventing/pkg/apis/eventing/v1beta1"
eventingv1client "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1"
servingv1client "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1"
"github.com/boson-project/faas"
"github.com/boson-project/faas/k8s"
)
type Describer struct {
Verbose bool
namespace string
servingClient *servingv1client.ServingV1alpha1Client
eventingClient *eventingv1client.EventingV1beta1Client
config *rest.Config
Verbose bool
namespace string
}
func NewDescriber(namespaceOverride string) (describer *Describer, err error) {
describer = &Describer{}
config, namespace, err := newClientConfig(namespaceOverride)
namespace, err := GetNamespace(namespaceOverride)
if err != nil {
return
}
describer.namespace = namespace
describer.servingClient, err = servingv1client.NewForConfig(config)
if err != nil {
return
}
describer.eventingClient, err = eventingv1client.NewForConfig(config)
if err != nil {
return
}
describer.config = config
describer.namespace = namespace
return
}
@ -46,24 +29,29 @@ func NewDescriber(namespaceOverride string) (describer *Describer, err error) {
// restricts to label-syntax, which is thus escaped. Therefore as a knative (kube) implementation
// detal proper full names have to be escaped on the way in and unescaped on the way out. ex:
// www.example-site.com -> www-example--site-com
func (describer *Describer) Describe(name string) (description faas.Description, err error) {
namespace := describer.namespace
servingClient := describer.servingClient
eventingClient := describer.eventingClient
func (d *Describer) Describe(name string) (description faas.Description, err error) {
serviceName, err := k8s.ToK8sAllowedName(name)
if err != nil {
return
}
service, err := servingClient.Services(namespace).Get(serviceName, metav1.GetOptions{})
servingClient, err := NewServingClient(d.namespace)
if err != nil {
return
}
serviceLabel := fmt.Sprintf("serving.knative.dev/service=%s", serviceName)
routes, err := servingClient.Routes(namespace).List(metav1.ListOptions{LabelSelector: serviceLabel})
eventingClient, err := NewEventingClient(d.namespace)
if err != nil {
return
}
service, err := servingClient.GetService(serviceName)
if err != nil {
return
}
routes, err := servingClient.ListRoutes(v1.WithService(serviceName))
if err != nil {
return
}
@ -73,7 +61,7 @@ func (describer *Describer) Describe(name string) (description faas.Description,
routeURLs = append(routeURLs, route.Status.URL.String())
}
triggers, err := eventingClient.Triggers(namespace).List(metav1.ListOptions{})
triggers, err := eventingClient.ListTriggers()
// IsNotFound -- Eventing is probably not installed on the cluster
if err != nil && !errors.IsNotFound(err) {
return

View File

@ -1,40 +1,45 @@
package knative
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
restclient "k8s.io/client-go/rest"
clientcmd "k8s.io/client-go/tools/clientcmd"
servingv1client "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1"
clientservingv1 "knative.dev/client/pkg/serving/v1"
"github.com/boson-project/faas/k8s"
)
const labelSelector = "bosonFunction"
const (
labelKey = "bosonFunction"
labelValue = "true"
)
type Lister struct {
Verbose bool
namespace string
client *servingv1client.ServingV1Client
}
func NewLister(namespaceOverride string) (l *Lister, err error) {
l = &Lister{}
config, namespace, err := newClientConfig(namespaceOverride)
namespace, err := GetNamespace(namespaceOverride)
if err != nil {
return
}
l.namespace = namespace
l.client, err = servingv1client.NewForConfig(config)
return
}
func (l *Lister) List() (names []string, err error) {
opts := metav1.ListOptions{LabelSelector: labelSelector}
lst, err := l.client.Services(l.namespace).List(opts)
client, err := NewServingClient(l.namespace)
if err != nil {
return
}
lst, err := client.ListServices(clientservingv1.WithLabel(labelKey, labelValue))
if err != nil {
return
}
for _, service := range lst.Items {
// Convert the "subdomain-encoded" (i.e. kube-service-friendly) name
// back out to a fully qualified service name.
@ -46,17 +51,3 @@ func (l *Lister) List() (names []string, err error) {
}
return
}
func newClientConfig(defaultNamespace string) (c *restclient.Config, namespace string, err error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
namespace = defaultNamespace
if defaultNamespace == "" {
namespace, _, err = clientConfig.Namespace()
if err != nil {
return
}
}
c, err = clientConfig.ClientConfig()
return
}

View File

@ -1,18 +1,21 @@
package knative
import (
"bytes"
"fmt"
"github.com/boson-project/faas/k8s"
"io"
"k8s.io/client-go/tools/clientcmd"
commands "knative.dev/client/pkg/kn/commands"
"os"
"time"
"github.com/boson-project/faas/k8s"
)
func NewRemover(namespaceOverride string) *Remover {
return &Remover{Namespace: namespaceOverride}
func NewRemover(namespaceOverride string) (remover *Remover, err error) {
remover = &Remover{}
namespace, err := GetNamespace(namespaceOverride)
if err != nil {
return
}
remover.Namespace = namespace
return
}
type Remover struct {
@ -22,42 +25,19 @@ type Remover struct {
func (remover *Remover) Remove(name string) (err error) {
project, err := k8s.ToK8sAllowedName(name)
serviceName, err := k8s.ToK8sAllowedName(name)
if err != nil {
return
}
var output io.Writer
if remover.Verbose {
output = os.Stdout
} else {
output = &bytes.Buffer{}
client, err := NewServingClient(remover.Namespace)
if err != nil {
return
}
p := commands.KnParams{}
p.Initialize()
p.Output = output
err = client.DeleteService(serviceName, time.Second*60)
if err != nil {
return err
}
if remover.Namespace == "" {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
remover.Namespace, _, _ = clientConfig.Namespace()
}
client, err := p.NewServingClient(remover.Namespace)
if err != nil {
return fmt.Errorf("remover failed to create new serving client: %v", err)
}
err = client.DeleteService(project, time.Second*30)
if err != nil {
if remover.Verbose {
err = fmt.Errorf("remover failed to delete the service: %v", err)
} else {
err = fmt.Errorf("remover failed to delete the service: %v.\nStdOut: %s", err, output.(*bytes.Buffer).String())
}
err = fmt.Errorf("knative remover failed to delete the service: %v", err)
}
return