Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for searching for CAPI clusters in the current context #154

Merged
merged 2 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/stores/capi/capi.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ version: v1alpha1
kubeconfigStores:
- kind: capi
config:
kubeconfigPath: "/home/user/.kube/management.config"
# Optionally specify a kubeconfigPath for a management cluster,
# if not specified your current kube context will be searched for any CAPI clusters
kubeconfigPath: "/home/user/.kube/management.config"
```
33 changes: 26 additions & 7 deletions pkg/store/kubeconfig_store_capi.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -55,18 +56,23 @@ func NewCapiStore(store types.KubeconfigStore, stateDir string) (*CapiStore, err

func (s *CapiStore) InitializeCapiStore() error {
s.Logger.Info("Initializing CAPI client")
k8sclient, err := s.getCapiClient()
k8sClient, err := s.getCapiClient()
if err != nil {
return err
}
s.Client = k8sclient
s.Client = k8sClient

return nil
}

// GetID returns the unique store ID
func (s *CapiStore) GetID() string {
return fmt.Sprintf("%s.%s", types.StoreKindCapi, *s.KubeconfigStore.ID)
id := "default"

if s.KubeconfigStore.ID != nil {
id = *s.KubeconfigStore.ID
}
return fmt.Sprintf("%s.%s", types.StoreKindCapi, id)
}

// GetKind returns the store kind
Expand All @@ -89,23 +95,27 @@ func (s *CapiStore) getCapiClient() (client.Client, error) {
utilruntime.Must(corev1.AddToScheme(scheme))
utilruntime.Must(clusterv1beta1.AddToScheme(scheme))

loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
if s.Config.KubeconfigPath != "" {
loadingRules = &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Config.KubeconfigPath}
}
// client from s.Config.KubeconfigPath
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Config.KubeconfigPath},
loadingRules,
&clientcmd.ConfigOverrides{})

restConfig, err := clientConfig.ClientConfig()
if err != nil {
return nil, fmt.Errorf("unable to create rest config: %v", err)
}

k8sclient, err := client.New(restConfig, client.Options{
k8sClient, err := client.New(restConfig, client.Options{
Scheme: scheme,
})
if err != nil {
return nil, fmt.Errorf("unable to create client: %v", err)
}
return k8sclient, nil
return k8sClient, nil
}

// StartSearch starts the search over the configured search paths
Expand All @@ -128,9 +138,18 @@ func (s *CapiStore) StartSearch(channel chan storetypes.SearchResult) {
clusters := &clusterv1beta1.ClusterList{}
err := s.Client.List(ctx, clusters)
if err != nil {
// if kubeconfigPath for mgmt cluster is defined error out and return if the Cluster CRD is not installed
// otherwise silently fail as our current context might not have CAPI installed
if s.Config.KubeconfigPath != "" || !meta.IsNoMatchError(err) {
channel <- storetypes.SearchResult{
KubeconfigPath: "",
Error: fmt.Errorf("unable to list clusters: %w", err),
}
return
}
s.Logger.Debug("CAPI: cannot listing v1beta1.Cluster resources, not currently connected to a cluster with CAPI installed")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably would be good to check the error string to if it indicates missing Cluster CRD. Or directly probe the K8s API for the Cluster CRD.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great idea, playing around with some ways to do that now, I'll have an update shortly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should now be fixed to return an error if there is an error other than the CRD not being found

channel <- storetypes.SearchResult{
KubeconfigPath: "",
Error: err,
}
return
}
Expand Down
2 changes: 1 addition & 1 deletion types/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ type StoreConfigAkamai struct {

type StoreConfigCapi struct {
// KubeconfigPath is the path on the local filesystem pointing to the kubeconfig
// for the management cluster
// for the management cluster. If none is specified the current context will be used to look up clusters
KubeconfigPath string `yaml:"kubeconfigPath"`
}

Expand Down
Loading