kubernetes: trim client-go dependency surface
Replace the full generated clientset and global Kubernetes scheme with a small local REST client layer and minimal scheme registration. This keeps the existing kubeconfig/auth and remote exec behavior while significantly reducing the linked and vendored Kubernetes dependency set. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/docker/buildx/driver"
|
||||
"github.com/docker/buildx/driver/kubernetes/execconn"
|
||||
"github.com/docker/buildx/driver/kubernetes/kubeclient"
|
||||
"github.com/docker/buildx/driver/kubernetes/manifest"
|
||||
"github.com/docker/buildx/driver/kubernetes/podchooser"
|
||||
"github.com/docker/buildx/store"
|
||||
@@ -24,9 +25,6 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
clientappsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -49,10 +47,9 @@ type Driver struct {
|
||||
minReplicas int
|
||||
deployment *appsv1.Deployment
|
||||
configMaps []*corev1.ConfigMap
|
||||
clientset *kubernetes.Clientset
|
||||
deploymentClient clientappsv1.DeploymentInterface
|
||||
podClient clientcorev1.PodInterface
|
||||
configMapClient clientcorev1.ConfigMapInterface
|
||||
deploymentClient kubeclient.DeploymentClient
|
||||
podClient kubeclient.PodClient
|
||||
configMapClient kubeclient.ConfigMapClient
|
||||
podChooser podchooser.PodChooser
|
||||
defaultLoad bool
|
||||
timeout time.Duration
|
||||
@@ -201,7 +198,6 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
|
||||
}
|
||||
|
||||
func (d *Driver) Dial(ctx context.Context) (net.Conn, error) {
|
||||
restClient := d.clientset.CoreV1().RESTClient()
|
||||
restClientConfig, err := d.clientConfig.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -221,7 +217,7 @@ func (d *Driver) Dial(ctx context.Context) (net.Conn, error) {
|
||||
var conn net.Conn
|
||||
err = tryWithBackoff(ctx, pod.Name, func() error {
|
||||
var err error
|
||||
conn, err = execconn.ExecConn(ctx, restClient, restClientConfig, pod.Namespace, pod.Name, containerName, cmd)
|
||||
conn, err = execconn.ExecConn(ctx, d.podClient.RESTClient(), restClientConfig, pod.Namespace, pod.Name, containerName, cmd)
|
||||
return err
|
||||
})
|
||||
return conn, err
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/buildx/driver/kubernetes/kubeclient"
|
||||
"github.com/sirupsen/logrus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
@@ -29,7 +29,7 @@ func ExecConn(ctx context.Context, restClient rest.Interface, restConfig *rest.C
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
TTY: false,
|
||||
}, scheme.ParameterCodec)
|
||||
}, kubeclient.ParameterCodec)
|
||||
exec, err := remotecommand.NewSPDYExecutor(restConfig, "POST", req.URL())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -10,13 +10,13 @@ import (
|
||||
"github.com/docker/buildx/driver"
|
||||
"github.com/docker/buildx/driver/bkimage"
|
||||
ctxkube "github.com/docker/buildx/driver/kubernetes/context"
|
||||
"github.com/docker/buildx/driver/kubernetes/kubeclient"
|
||||
"github.com/docker/buildx/driver/kubernetes/manifest"
|
||||
"github.com/docker/buildx/driver/kubernetes/podchooser"
|
||||
dockerclient "github.com/moby/moby/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
@@ -116,16 +116,11 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(restClientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := &Driver{
|
||||
factory: f,
|
||||
clientConfig: cc,
|
||||
InitConfig: cfg,
|
||||
clientset: clientset,
|
||||
}
|
||||
|
||||
deploymentOpt, loadbalance, namespace, defaultLoad, timeout, err := f.processDriverOpts(deploymentName, namespace, cfg)
|
||||
@@ -143,9 +138,13 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
|
||||
|
||||
d.minReplicas = int(deploymentOpt.Replicas)
|
||||
|
||||
d.deploymentClient = clientset.AppsV1().Deployments(namespace)
|
||||
d.podClient = clientset.CoreV1().Pods(namespace)
|
||||
d.configMapClient = clientset.CoreV1().ConfigMaps(namespace)
|
||||
clients, err := kubeclient.New(restClientConfig, namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.deploymentClient = clients.Deployments
|
||||
d.podClient = clients.Pods
|
||||
d.configMapClient = clients.ConfigMaps
|
||||
|
||||
switch loadbalance {
|
||||
case LoadbalanceSticky:
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
package kubeclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type DeploymentClient interface {
|
||||
Get(ctx context.Context, name string, opts metav1.GetOptions) (*appsv1.Deployment, error)
|
||||
Create(ctx context.Context, deployment *appsv1.Deployment, opts metav1.CreateOptions) (*appsv1.Deployment, error)
|
||||
Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
|
||||
}
|
||||
|
||||
type ConfigMapClient interface {
|
||||
Create(ctx context.Context, configMap *corev1.ConfigMap, opts metav1.CreateOptions) (*corev1.ConfigMap, error)
|
||||
Update(ctx context.Context, configMap *corev1.ConfigMap, opts metav1.UpdateOptions) (*corev1.ConfigMap, error)
|
||||
Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
|
||||
}
|
||||
|
||||
type PodClient interface {
|
||||
List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error)
|
||||
RESTClient() rest.Interface
|
||||
}
|
||||
|
||||
type Clients struct {
|
||||
Deployments DeploymentClient
|
||||
ConfigMaps ConfigMapClient
|
||||
Pods PodClient
|
||||
}
|
||||
|
||||
func New(config *rest.Config, namespace string) (*Clients, error) {
|
||||
httpClient, err := rest.HTTPClientFor(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appsClient, err := newRESTClient(config, httpClient, appsv1.SchemeGroupVersion, "/apis")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
coreClient, err := newRESTClient(config, httpClient, corev1.SchemeGroupVersion, "/api")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Clients{
|
||||
Deployments: &deploymentClient{client: appsClient, namespace: namespace},
|
||||
ConfigMaps: &configMapClient{client: coreClient, namespace: namespace},
|
||||
Pods: &podClient{client: coreClient, namespace: namespace},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newRESTClient(config *rest.Config, httpClient *http.Client, gv schema.GroupVersion, apiPath string) (rest.Interface, error) {
|
||||
cfg := *config
|
||||
cfg.GroupVersion = &gv
|
||||
cfg.APIPath = apiPath
|
||||
cfg.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(Scheme, Codecs).WithoutConversion()
|
||||
if cfg.UserAgent == "" {
|
||||
cfg.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
return rest.RESTClientForConfigAndClient(&cfg, httpClient)
|
||||
}
|
||||
|
||||
type deploymentClient struct {
|
||||
client rest.Interface
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (c *deploymentClient) Get(ctx context.Context, name string, opts metav1.GetOptions) (*appsv1.Deployment, error) {
|
||||
result := &appsv1.Deployment{}
|
||||
err := c.client.Get().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("deployments").
|
||||
Name(name).
|
||||
VersionedParams(&opts, ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *deploymentClient) Create(ctx context.Context, deployment *appsv1.Deployment, opts metav1.CreateOptions) (*appsv1.Deployment, error) {
|
||||
result := &appsv1.Deployment{}
|
||||
err := c.client.Post().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("deployments").
|
||||
VersionedParams(&opts, ParameterCodec).
|
||||
Body(deployment).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *deploymentClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("deployments").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
type configMapClient struct {
|
||||
client rest.Interface
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (c *configMapClient) Create(ctx context.Context, configMap *corev1.ConfigMap, opts metav1.CreateOptions) (*corev1.ConfigMap, error) {
|
||||
result := &corev1.ConfigMap{}
|
||||
err := c.client.Post().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("configmaps").
|
||||
VersionedParams(&opts, ParameterCodec).
|
||||
Body(configMap).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *configMapClient) Update(ctx context.Context, configMap *corev1.ConfigMap, opts metav1.UpdateOptions) (*corev1.ConfigMap, error) {
|
||||
result := &corev1.ConfigMap{}
|
||||
err := c.client.Put().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("configmaps").
|
||||
Name(configMap.Name).
|
||||
VersionedParams(&opts, ParameterCodec).
|
||||
Body(configMap).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *configMapClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("configmaps").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
type podClient struct {
|
||||
client rest.Interface
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (c *podClient) List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error) {
|
||||
result := &corev1.PodList{}
|
||||
err := c.client.Get().
|
||||
UseProtobufAsDefault().
|
||||
Namespace(c.namespace).
|
||||
Resource("pods").
|
||||
VersionedParams(&opts, ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *podClient) RESTClient() rest.Interface {
|
||||
return c.client
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package kubeclient
|
||||
|
||||
import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
|
||||
func init() {
|
||||
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(corev1.AddToScheme(Scheme))
|
||||
utilruntime.Must(appsv1.AddToScheme(Scheme))
|
||||
}
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/docker/buildx/driver/kubernetes/kubeclient"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/serialx/hashring"
|
||||
"github.com/sirupsen/logrus"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
type PodChooser interface {
|
||||
@@ -21,7 +21,7 @@ type PodChooser interface {
|
||||
|
||||
type RandomPodChooser struct {
|
||||
RandSource rand.Source
|
||||
PodClient clientcorev1.PodInterface
|
||||
PodClient kubeclient.PodClient
|
||||
Deployment *appsv1.Deployment
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (pc *RandomPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error)
|
||||
|
||||
type StickyPodChooser struct {
|
||||
Key string
|
||||
PodClient clientcorev1.PodInterface
|
||||
PodClient kubeclient.PodClient
|
||||
Deployment *appsv1.Deployment
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (pc *StickyPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error)
|
||||
return podMap[chosen], nil
|
||||
}
|
||||
|
||||
func ListRunningPods(ctx context.Context, client clientcorev1.PodInterface, depl *appsv1.Deployment) ([]*corev1.Pod, error) {
|
||||
func ListRunningPods(ctx context.Context, client kubeclient.PodClient, depl *appsv1.Deployment) ([]*corev1.Pod, error) {
|
||||
selector, err := metav1.LabelSelectorAsSelector(depl.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user