164 lines
5.4 KiB
Go
164 lines
5.4 KiB
Go
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",
|
||
}
|
||
|
||
// 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
|
||
}
|