Add clustermap object and interface

This commit adds cluster map api object, cluster map
interface and it's implementation built on top of cluster map api
object.

Important note:
ClusterMap interface needs a method to identify namespace of the
cluster, it can't be a part of api object, because real source for
cluster namespace is cluster object from cluster-api upstream lib.
This will need further design discussion on how we will find
cluster-api kind: Cluster object in our manifests. For now, there
is dummy "default" namespace being used

Change-Id: I8175f54abbe77331f0c87c0bde50857ee5c0eb1d
This commit is contained in:
Kostiantyn Kalynovskyi
2020-09-08 22:57:06 -05:00
parent 233bbda0e0
commit 0a7661ab7c
14 changed files with 305 additions and 91 deletions

View File

@@ -17,11 +17,10 @@ package kubeconfig
import (
"path/filepath"
"opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/cluster/clustermap"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/errors"
"opendev.org/airship/airshipctl/pkg/log"
"opendev.org/airship/airshipctl/pkg/util"
)
@@ -41,7 +40,7 @@ type Builder struct {
clusterName string
root string
clusterMap *v1alpha1.ClusterMap
clusterMap clustermap.ClusterMap
}
// WithPath allows to set path to prexisting kubeconfig
@@ -57,7 +56,7 @@ func (b *Builder) WithBundle(bundlePath string) *Builder {
}
// WithClusterMap allows to set a parent cluster, that can be used to extract kubeconfig for target cluster
func (b *Builder) WithClusterMap(cMap *v1alpha1.ClusterMap) *Builder {
func (b *Builder) WithClusterMap(cMap clustermap.ClusterMap) *Builder {
b.clusterMap = cMap
return b
}
@@ -101,16 +100,5 @@ func (b *Builder) fromParent() bool {
if b.clusterMap == nil {
return false
}
currentCluster, exists := b.clusterMap.Map[b.clusterName]
if !exists {
log.Debugf("cluster %s is not defined in cluster map %v", b.clusterName, b.clusterMap)
return false
}
// Check if DynamicKubeConfig is enabled, if so that means, we should get kubeconfig
// for this cluster from its parent
if currentCluster.Parent == "" || !currentCluster.DynamicKubeConfig {
log.Debugf("dynamic kubeconfig or parent cluster is not set for cluster %s", b.clusterName)
return false
}
return true
return b.clusterMap.DynamicKubeConfig(b.clusterName)
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/cluster/clustermap"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
"opendev.org/airship/airshipctl/pkg/util"
@@ -66,7 +67,7 @@ func TestBuilder(t *testing.T) {
},
}
builder := kubeconfig.NewBuilder().
WithClusterMap(clusterMap).
WithClusterMap(clustermap.NewClusterMap(clusterMap)).
WithClusterName(childCluster)
kube := builder.Build()
// This should not be implemented yet, and we need to check that we are getting there
@@ -81,7 +82,7 @@ func TestBuilder(t *testing.T) {
t.Run("No current cluster, fall to default", func(t *testing.T) {
clusterMap := &v1alpha1.ClusterMap{}
builder := kubeconfig.NewBuilder().
WithClusterMap(clusterMap).
WithClusterMap(clustermap.NewClusterMap(clusterMap)).
WithClusterName("some-cluster")
kube := builder.Build()
// We should get a default value for cluster since we don't have some-cluster set
@@ -92,7 +93,7 @@ func TestBuilder(t *testing.T) {
assert.Equal(t, path, actualPath)
})
t.Run("No parent cluster is defined, fall to default", func(t *testing.T) {
t.Run("Dynamic, but no parent", func(t *testing.T) {
childCluster := "child"
clusterMap := &v1alpha1.ClusterMap{
Map: map[string]*v1alpha1.Cluster{
@@ -102,15 +103,15 @@ func TestBuilder(t *testing.T) {
},
}
builder := kubeconfig.NewBuilder().
WithClusterMap(clusterMap).
WithClusterMap(clustermap.NewClusterMap(clusterMap)).
WithClusterName(childCluster)
kube := builder.Build()
// We should get a default value for cluster, as we can't find parent cluster
actualPath, cleanup, err := kube.GetFile()
defer cleanup()
require.NoError(t, err)
path := filepath.Join(util.UserHomeDir(), config.AirshipConfigDir, kubeconfig.KubeconfigDefaultFileName)
assert.Equal(t, path, actualPath)
filePath, cleanup, err := kube.GetFile()
require.Error(t, err)
require.Contains(t, err.Error(), "not implemented")
assert.Equal(t, "", filePath)
require.Nil(t, cleanup)
})
t.Run("Default source", func(t *testing.T) {
@@ -119,8 +120,8 @@ func TestBuilder(t *testing.T) {
// When ClusterMap is specified, but it doesn't have cluster-name defined, and no
// other sources provided,
actualPath, cleanup, err := kube.GetFile()
defer cleanup()
require.NoError(t, err)
defer cleanup()
path := filepath.Join(util.UserHomeDir(), config.AirshipConfigDir, kubeconfig.KubeconfigDefaultFileName)
assert.Equal(t, path, actualPath)
})