Files

256 lines
9.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package client
import (
"context"
"fmt"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
var environmentGVR = schema.GroupVersionResource{
Group: "fission.io",
Version: "v1",
Resource: "environments",
}
var packageGVR = schema.GroupVersionResource{
Group: "fission.io",
Version: "v1",
Resource: "packages",
}
var functionGVR = schema.GroupVersionResource{
Group: "fission.io",
Version: "v1",
Resource: "functions",
}
var httpTriggerGVR = schema.GroupVersionResource{
Group: "fission.io",
Version: "v1",
Resource: "httptriggers",
}
// Client хранит клиентов Kubernetes API для работы с CRD Fission.
type Client struct {
DynClient dynamic.Interface
K8sClient kubernetes.Interface
Namespace string
}
// New создает Kubernetes clients из kubeconfig/context.
func New(kubeconfigPath, kubeContext, namespace string) (*Client, error) {
cfg, err := buildConfig(kubeconfigPath, kubeContext)
if err != nil {
return nil, err
}
dynClient, err := dynamic.NewForConfig(cfg)
if err != nil {
return nil, fmt.Errorf("create dynamic client: %w", err)
}
k8sClient, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, fmt.Errorf("create kubernetes client: %w", err)
}
return &Client{
DynClient: dynClient,
K8sClient: k8sClient,
Namespace: namespace,
}, nil
}
func buildConfig(kubeconfigPath, kubeContext string) (*rest.Config, error) {
loadingRules := &clientcmd.ClientConfigLoadingRules{}
if kubeconfigPath != "" {
loadingRules.ExplicitPath = kubeconfigPath
}
overrides := &clientcmd.ConfigOverrides{}
if kubeContext != "" {
overrides.CurrentContext = kubeContext
}
clientCfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)
cfg, err := clientCfg.ClientConfig()
if err != nil {
return nil, fmt.Errorf("build kube config: %w", err)
}
return cfg, nil
}
// CreateEnvironment создает объект Environment в заданном namespace.
func (c *Client) CreateEnvironment(ctx context.Context, environment *unstructured.Unstructured) (*unstructured.Unstructured, error) {
createdEnvironment, err := c.DynClient.Resource(environmentGVR).Namespace(environment.GetNamespace()).Create(ctx, environment, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("create environment %q: %w", environment.GetName(), err)
}
return createdEnvironment, nil
}
// GetEnvironment получает объект Environment по имени.
func (c *Client) GetEnvironment(ctx context.Context, namespace, name string) (*unstructured.Unstructured, error) {
environment, err := c.DynClient.Resource(environmentGVR).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("get environment %q: %w", name, err)
}
return environment, nil
}
// UpdateEnvironment обновляет существующий объект Environment.
func (c *Client) UpdateEnvironment(ctx context.Context, environment *unstructured.Unstructured) (*unstructured.Unstructured, error) {
updatedEnvironment, err := c.DynClient.Resource(environmentGVR).Namespace(environment.GetNamespace()).Update(ctx, environment, metav1.UpdateOptions{})
if err != nil {
return nil, fmt.Errorf("update environment %q: %w", environment.GetName(), err)
}
return updatedEnvironment, nil
}
// DeleteEnvironment удаляет объект Environment по имени.
func (c *Client) DeleteEnvironment(ctx context.Context, namespace, name string) error {
err := c.DynClient.Resource(environmentGVR).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("delete environment %q: %w", name, err)
}
return nil
}
// IsNotFound возвращает true для ошибок Kubernetes типа NotFound.
func IsNotFound(err error) bool {
return apierrors.IsNotFound(err)
}
// CreatePackage создает объект Package в заданном namespace.
func (c *Client) CreatePackage(ctx context.Context, pkg *unstructured.Unstructured) (*unstructured.Unstructured, error) {
createdPackage, err := c.DynClient.Resource(packageGVR).Namespace(pkg.GetNamespace()).Create(ctx, pkg, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("create package %q: %w", pkg.GetName(), err)
}
return createdPackage, nil
}
// GetPackage получает объект Package по имени.
func (c *Client) GetPackage(ctx context.Context, namespace, name string) (*unstructured.Unstructured, error) {
pkg, err := c.DynClient.Resource(packageGVR).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("get package %q: %w", name, err)
}
return pkg, nil
}
// UpdatePackage обновляет существующий объект Package.
func (c *Client) UpdatePackage(ctx context.Context, pkg *unstructured.Unstructured) (*unstructured.Unstructured, error) {
updatedPackage, err := c.DynClient.Resource(packageGVR).Namespace(pkg.GetNamespace()).Update(ctx, pkg, metav1.UpdateOptions{})
if err != nil {
return nil, fmt.Errorf("update package %q: %w", pkg.GetName(), err)
}
return updatedPackage, nil
}
// DeletePackage удаляет объект Package по имени.
func (c *Client) DeletePackage(ctx context.Context, namespace, name string) error {
err := c.DynClient.Resource(packageGVR).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("delete package %q: %w", name, err)
}
return nil
}
// CreateFunction создает объект Function в заданном namespace.
func (c *Client) CreateFunction(ctx context.Context, fn *unstructured.Unstructured) (*unstructured.Unstructured, error) {
createdFunction, err := c.DynClient.Resource(functionGVR).Namespace(fn.GetNamespace()).Create(ctx, fn, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("create function %q: %w", fn.GetName(), err)
}
return createdFunction, nil
}
// GetFunction получает объект Function по имени.
func (c *Client) GetFunction(ctx context.Context, namespace, name string) (*unstructured.Unstructured, error) {
fn, err := c.DynClient.Resource(functionGVR).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("get function %q: %w", name, err)
}
return fn, nil
}
// UpdateFunction обновляет существующий объект Function.
func (c *Client) UpdateFunction(ctx context.Context, fn *unstructured.Unstructured) (*unstructured.Unstructured, error) {
updatedFunction, err := c.DynClient.Resource(functionGVR).Namespace(fn.GetNamespace()).Update(ctx, fn, metav1.UpdateOptions{})
if err != nil {
return nil, fmt.Errorf("update function %q: %w", fn.GetName(), err)
}
return updatedFunction, nil
}
// DeleteFunction удаляет объект Function по имени.
func (c *Client) DeleteFunction(ctx context.Context, namespace, name string) error {
err := c.DynClient.Resource(functionGVR).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("delete function %q: %w", name, err)
}
return nil
}
// CreateHTTPTrigger создает объект HTTPTrigger в заданном namespace.
func (c *Client) CreateHTTPTrigger(ctx context.Context, trigger *unstructured.Unstructured) (*unstructured.Unstructured, error) {
createdTrigger, err := c.DynClient.Resource(httpTriggerGVR).Namespace(trigger.GetNamespace()).Create(ctx, trigger, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("create http trigger %q: %w", trigger.GetName(), err)
}
return createdTrigger, nil
}
// GetHTTPTrigger получает объект HTTPTrigger по имени.
func (c *Client) GetHTTPTrigger(ctx context.Context, namespace, name string) (*unstructured.Unstructured, error) {
trigger, err := c.DynClient.Resource(httpTriggerGVR).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("get http trigger %q: %w", name, err)
}
return trigger, nil
}
// UpdateHTTPTrigger обновляет существующий объект HTTPTrigger.
func (c *Client) UpdateHTTPTrigger(ctx context.Context, trigger *unstructured.Unstructured) (*unstructured.Unstructured, error) {
updatedTrigger, err := c.DynClient.Resource(httpTriggerGVR).Namespace(trigger.GetNamespace()).Update(ctx, trigger, metav1.UpdateOptions{})
if err != nil {
return nil, fmt.Errorf("update http trigger %q: %w", trigger.GetName(), err)
}
return updatedTrigger, nil
}
// DeleteHTTPTrigger удаляет объект HTTPTrigger по имени.
func (c *Client) DeleteHTTPTrigger(ctx context.Context, namespace, name string) error {
err := c.DynClient.Resource(httpTriggerGVR).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("delete http trigger %q: %w", name, err)
}
return nil
}