Skip to content

Commit

Permalink
Implement AP client factory in terms of k0s client factory
Browse files Browse the repository at this point in the history
The Autopilot client factory was basically a copy of the k0s client
factory. Implement the former using the latter and add deprecation notes
to all the old types and methods.

Signed-off-by: Tom Wieczorek <[email protected]>
  • Loading branch information
twz123 committed Sep 10, 2024
1 parent 3b93e5c commit f3c3014
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 156 deletions.
15 changes: 6 additions & 9 deletions cmd/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,15 +575,12 @@ func (c *command) start(ctx context.Context) error {
EnableWorker: c.EnableWorker,
})

restConfig, err := adminClientFactory.GetRESTConfig()
if err != nil {
return err
}
apClientFactory, err := apclient.NewClientFactory(restConfig)
if err != nil {
return err
}
clusterComponents.Add(ctx, controller.NewUpdateProber(apClientFactory, leaderElector))
clusterComponents.Add(ctx, controller.NewUpdateProber(
&apclient.ClientFactory{
ClientFactoryInterface: adminClientFactory,
},
leaderElector,
))

perfTimer.Checkpoint("starting-cluster-components-init")
// init Cluster components
Expand Down
38 changes: 12 additions & 26 deletions internal/autopilot/testutil/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,11 @@
package testutil

import (
apclient "github.com/k0sproject/k0s/pkg/client/clientset"
apclientfake "github.com/k0sproject/k0s/pkg/client/clientset/fake"
extclientfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"

k0stestutil "github.com/k0sproject/k0s/internal/testutil"

Check failure on line 18 in internal/autopilot/testutil/client.go

View workflow job for this annotation

GitHub Actions / Lint

import 'github.com/k0sproject/k0s/internal/testutil' is not allowed from list 'tests': Usage of test code outside of tests. (depguard)
"github.com/k0sproject/k0s/pkg/autopilot/client"

extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest"
)

type FakeClientOpt func(config fakeClientConfig) fakeClientConfig
Expand Down Expand Up @@ -52,39 +47,30 @@ func WithAutopilotObjects(objects ...runtime.Object) FakeClientOpt {
}

// NewFakeClientFactory creates new client factory
// Deprecated: Use [k0stestutil.NewFakeClientFactory] instead.
func NewFakeClientFactory(opts ...FakeClientOpt) client.FactoryInterface {
config := fakeClientConfig{}
for _, opt := range opts {
config = opt(config)
}

return &fakeClientFactory{
client: fake.NewSimpleClientset(config.kubeObjects...),
clientAutopilot: apclientfake.NewSimpleClientset(config.autopilotObjects...),
clientExtensions: extclientfake.NewSimpleClientset(config.extensionObjects...).ApiextensionsV1(),
FakeClientFactory: k0stestutil.NewFakeClientFactory(config.kubeObjects...),
}
}

type fakeClientFactory struct {
client kubernetes.Interface
clientAutopilot apclient.Interface
clientExtensions extclient.ApiextensionsV1Interface
*k0stestutil.FakeClientFactory
}

var _ client.FactoryInterface = (*fakeClientFactory)(nil)

func (f fakeClientFactory) GetClient() (kubernetes.Interface, error) {
return f.client, nil
}

func (f fakeClientFactory) GetK0sClient() (apclient.Interface, error) {
return f.clientAutopilot, nil
}

// Deprecated: Use [fakeClientFactory.GetAPIExtensionsClient] instead.
func (f fakeClientFactory) GetExtensionClient() (extclient.ApiextensionsV1Interface, error) {
return f.clientExtensions, nil
}
client, err := f.GetAPIExtensionsClient()
if err != nil {
return nil, err
}

func (f fakeClientFactory) GetRESTConfig() (*rest.Config, error) {
panic("GetRESTConfig not implemented for fakeClientFactory")
return client.ApiextensionsV1(), nil
}
88 changes: 14 additions & 74 deletions pkg/autopilot/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,98 +15,38 @@
package client

import (
"sync"

apclient "github.com/k0sproject/k0s/pkg/client/clientset"
extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
kubeutil "github.com/k0sproject/k0s/pkg/kubernetes"

apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

// FactoryInterface is a collection of kubernetes clientset interfaces.
// Deprecated: Use [kubeutil.ClientFactoryInterface] instead.
type FactoryInterface interface {
GetClient() (kubernetes.Interface, error)
GetK0sClient() (apclient.Interface, error)
GetExtensionClient() (extclient.ApiextensionsV1Interface, error)
GetAPIExtensionsClient() (apiextensionsclientset.Interface, error)
GetExtensionClient() (extclient.ApiextensionsV1Interface, error) // Deprecated: Use [FactoryInterface.GetAPIExtensionsClient] instead.
GetRESTConfig() (*rest.Config, error)
}

type clientFactory struct {
client kubernetes.Interface
clientAutopilot apclient.Interface
clientExtensions extclient.ApiextensionsV1Interface
restConfig *rest.Config

mutex sync.Mutex
}

var _ FactoryInterface = (*clientFactory)(nil)

func NewClientFactory(config *rest.Config) (FactoryInterface, error) {
return &clientFactory{restConfig: config}, nil
}

// GetClient returns the core kubernetes clientset
func (cf *clientFactory) GetClient() (kubernetes.Interface, error) {
cf.mutex.Lock()
defer cf.mutex.Unlock()
var err error

if cf.client != nil {
return cf.client, nil
}

client, err := kubernetes.NewForConfig(cf.restConfig)
if err != nil {
return nil, err
}

cf.client = client

return cf.client, nil
}

// GetK0sClient returns the clientset for autopilot
func (cf *clientFactory) GetK0sClient() (apclient.Interface, error) {
cf.mutex.Lock()
defer cf.mutex.Unlock()
var err error

if cf.clientAutopilot != nil {
return cf.clientAutopilot, nil
}

client, err := apclient.NewForConfig(cf.restConfig)
if err != nil {
return nil, err
}

cf.clientAutopilot = client

return cf.clientAutopilot, nil
// Deprecated: Use [kubeutil.ClientFactory] instead.
type ClientFactory struct {
kubeutil.ClientFactoryInterface
}

// GetExtensionClient returns the clientset for kubernetes extensions
func (cf *clientFactory) GetExtensionClient() (extclient.ApiextensionsV1Interface, error) {
cf.mutex.Lock()
defer cf.mutex.Unlock()
var err error

if cf.clientExtensions != nil {
return cf.clientExtensions, nil
}
var _ FactoryInterface = (*ClientFactory)(nil)

client, err := extclient.NewForConfig(cf.restConfig)
// Deprecated: Use [ClientFactory.GetAPIExtensionsClient] instead.
func (cf *ClientFactory) GetExtensionClient() (extclient.ApiextensionsV1Interface, error) {
client, err := cf.GetAPIExtensionsClient()
if err != nil {
return nil, err
}

cf.clientExtensions = client

return cf.clientExtensions, nil
}

func (cf *clientFactory) GetRESTConfig() (*rest.Config, error) {
return cf.restConfig, nil
return client.ApiextensionsV1(), nil
}
9 changes: 2 additions & 7 deletions pkg/component/controller/autopilot.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,8 @@ func (a *Autopilot) Init(ctx context.Context) error {
func (a *Autopilot) Start(ctx context.Context) error {
log := logrus.WithFields(logrus.Fields{"component": "autopilot"})

restConfig, err := a.AdminClientFactory.GetRESTConfig()
if err != nil {
return fmt.Errorf("creating autopilot client factory error: %w", err)
}
autopilotClientFactory, err := apcli.NewClientFactory(restConfig)
if err != nil {
return fmt.Errorf("creating autopilot client factory error: %w", err)
autopilotClientFactory := &apcli.ClientFactory{
ClientFactoryInterface: a.AdminClientFactory,
}

autopilotRoot, err := apcont.NewRootController(aproot.RootConfig{
Expand Down
32 changes: 12 additions & 20 deletions pkg/component/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import (
"time"

"github.com/k0sproject/k0s/internal/pkg/dir"
"github.com/k0sproject/k0s/pkg/autopilot/client"
"github.com/k0sproject/k0s/pkg/component/manager"
"github.com/k0sproject/k0s/pkg/component/prober"
kubeutil "github.com/k0sproject/k0s/pkg/kubernetes"
"github.com/sirupsen/logrus"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
Expand Down Expand Up @@ -167,26 +167,18 @@ func (sh *statusHandler) getCurrentStatus(ctx context.Context) K0sStatus {
return status
}

func (sh *statusHandler) buildWorkerSideKubeAPIClient(ctx context.Context) (kubernetes.Interface, error) {
var restConfig *rest.Config
var err error
timeout, cancel := context.WithTimeout(ctx, defaultPollTimeout)
defer cancel()
if err := wait.PollUntilWithContext(timeout, defaultPollDuration, func(ctx context.Context) (done bool, err error) {
if restConfig, err = sh.Status.CertManager.GetRestConfig(ctx); err != nil {
func (sh *statusHandler) buildWorkerSideKubeAPIClient(ctx context.Context) (client kubernetes.Interface, err error) {
err = wait.PollUntilContextTimeout(ctx, defaultPollDuration, defaultPollTimeout, true, func(ctx context.Context) (_ bool, err error) {
factory := kubeutil.ClientFactory{LoadRESTConfig: func() (*rest.Config, error) {
return sh.Status.CertManager.GetRestConfig(ctx)
}}

client, err = factory.GetClient()
if err != nil {
return false, nil
}
return true, nil
}); err != nil {
return nil, err
}
factory, err := client.NewClientFactory(restConfig)
if err != nil {
return nil, err
}
client, err := factory.GetClient()
if err != nil {
return nil, err
}
return client, nil
})

return client, err
}
30 changes: 10 additions & 20 deletions pkg/component/worker/autopilot.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package worker

import (
"context"
"errors"
"fmt"
"time"

Expand All @@ -27,6 +26,7 @@ import (
aproot "github.com/k0sproject/k0s/pkg/autopilot/controller/root"
"github.com/k0sproject/k0s/pkg/component/manager"
"github.com/k0sproject/k0s/pkg/config"
"github.com/k0sproject/k0s/pkg/kubernetes"
"github.com/sirupsen/logrus"

"k8s.io/apimachinery/pkg/util/wait"
Expand All @@ -53,35 +53,25 @@ func (a *Autopilot) Start(ctx context.Context) error {
log := logrus.WithFields(logrus.Fields{"component": "autopilot"})

// Wait 5 mins till we see kubelet auth config in place
timeout, cancel := context.WithTimeout(ctx, defaultPollTimeout)
defer cancel()

var restConfig *rest.Config
// wait.PollUntilWithContext passes it is own ctx argument as a ctx to the given function
// wait.PollUntilContextTimeout passes it is own ctx argument as a ctx to the given function
// Poll until the kubelet config can be loaded successfully, as this is the access to the kube api
// needed by autopilot.
if err := wait.PollUntilWithContext(timeout, defaultPollDuration, func(ctx context.Context) (done bool, err error) {
log.Debugf("Attempting to load autopilot client config")
var restConfig *rest.Config
if err := wait.PollUntilContextTimeout(ctx, defaultPollDuration, defaultPollTimeout, true, func(ctx context.Context) (_ bool, err error) {
log.Debug("Attempting to load autopilot client config")
if restConfig, err = a.CertManager.GetRestConfig(ctx); err != nil {
log.WithError(err).Warnf("Failed to load autopilot client config, retrying in %v", defaultPollDuration)
log.WithError(err).Warn("Failed to load autopilot client config, retrying in ", defaultPollDuration)
return false, nil
}

return true, nil
}); err != nil {
return fmt.Errorf("unable to create autopilot client: %w", err)
}

// Without the config, there is nothing that we can do.

if restConfig == nil {
return errors.New("unable to create an autopilot client -- timed out")
return fmt.Errorf("unable to create autopilot client: %w", context.Cause(ctx))
}

autopilotClientFactory, err := apcli.NewClientFactory(restConfig)
if err != nil {
return fmt.Errorf("creating autopilot client factory error: %w", err)
}
autopilotClientFactory := &apcli.ClientFactory{ClientFactoryInterface: &kubernetes.ClientFactory{
LoadRESTConfig: func() (*rest.Config, error) { return restConfig, nil },
}}

log.Info("Autopilot client factory created, booting up worker root controller")
autopilotRoot, err := apcont.NewRootWorker(aproot.RootConfig{
Expand Down

0 comments on commit f3c3014

Please sign in to comment.