Merge "Use site-wide kubeconfig only on demand"
This commit is contained in:
commit
e38f4fbf4c
@ -126,6 +126,7 @@ metadata:
|
|||||||
name: clusterctl-move
|
name: clusterctl-move
|
||||||
clusterName: target-cluster
|
clusterName: target-cluster
|
||||||
config:
|
config:
|
||||||
|
siteWideKubeconfig: true
|
||||||
executorRef:
|
executorRef:
|
||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
kind: Clusterctl
|
kind: Clusterctl
|
||||||
|
@ -32,6 +32,7 @@ type Phase struct {
|
|||||||
// phase runner object which should contain runner configuration
|
// phase runner object which should contain runner configuration
|
||||||
type PhaseConfig struct {
|
type PhaseConfig struct {
|
||||||
ExecutorRef *corev1.ObjectReference `json:"executorRef"`
|
ExecutorRef *corev1.ObjectReference `json:"executorRef"`
|
||||||
|
SiteWideKubeconfig bool `json:"siteWideKubeconfig,omitempty"`
|
||||||
DocumentEntryPoint string `json:"documentEntryPoint"`
|
DocumentEntryPoint string `json:"documentEntryPoint"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +83,18 @@ func (cmd *GetKubeconfigCommand) RunE(cfgFactory config.Factory, writer io.Write
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var siteWide bool
|
||||||
|
if cmd.ClusterName == "" {
|
||||||
|
siteWide = true
|
||||||
|
}
|
||||||
|
|
||||||
kubeconf := kubeconfig.NewBuilder().
|
kubeconf := kubeconfig.NewBuilder().
|
||||||
WithBundle(helper.PhaseConfigBundle()).
|
WithBundle(helper.PhaseConfigBundle()).
|
||||||
WithClusterctlClient(client).
|
WithClusterctlClient(client).
|
||||||
WithClusterMap(cMap).
|
WithClusterMap(cMap).
|
||||||
WithClusterName(cmd.ClusterName).
|
WithClusterName(cmd.ClusterName).
|
||||||
WithTempRoot(helper.WorkDir()).
|
WithTempRoot(helper.WorkDir()).
|
||||||
|
SiteWide(siteWide).
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
return kubeconf.Write(writer)
|
return kubeconf.Write(writer)
|
||||||
|
@ -41,6 +41,7 @@ func NewBuilder() *Builder {
|
|||||||
// Builder is an object that allows to build a kubeconfig based on various provided sources
|
// Builder is an object that allows to build a kubeconfig based on various provided sources
|
||||||
// such as path to kubeconfig, path to bundle that should contain kubeconfig and parent cluster
|
// such as path to kubeconfig, path to bundle that should contain kubeconfig and parent cluster
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
|
siteWide bool
|
||||||
clusterName string
|
clusterName string
|
||||||
root string
|
root string
|
||||||
|
|
||||||
@ -88,11 +89,21 @@ func (b *Builder) WithFilesystem(fs fs.FileSystem) *Builder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SiteWide allows to build kubeconfig for the entire site.
|
||||||
|
// If set to true ClusterName will be ignored, since all clusters are requested.
|
||||||
|
func (b *Builder) SiteWide(t bool) *Builder {
|
||||||
|
b.siteWide = t
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// Build site kubeconfig, ignores, but logs, errors that happen when building individual
|
// Build site kubeconfig, ignores, but logs, errors that happen when building individual
|
||||||
// kubeconfigs. We need this behavior because, some clusters may not yet be deployed
|
// kubeconfigs. We need this behavior because, some clusters may not yet be deployed
|
||||||
// and their kubeconfig is inaccessible yet, but will be accessible at later phases
|
// and their kubeconfig is inaccessible yet, but will be accessible at later phases
|
||||||
// If builder can't build kubeconfig for specific cluster, its context will not be present
|
// If builder can't build kubeconfig for specific cluster, its context will not be present
|
||||||
// in final kubeconfig. User of kubeconfig, will receive error stating that context doesn't exist
|
// in final kubeconfig. User of kubeconfig, will receive error stating that context doesn't exist
|
||||||
|
// To request site-wide kubeconfig use builder method SiteWide(true).
|
||||||
|
// To request a single cluster kubeconfig use methods WithClusterName("my-cluster").SiteWide(false)
|
||||||
|
// ClusterName is ignored if SiteWide(true) is used.
|
||||||
func (b *Builder) Build() Interface {
|
func (b *Builder) Build() Interface {
|
||||||
return NewKubeConfig(b.build, InjectFileSystem(b.fs), InjectTempRoot(b.root))
|
return NewKubeConfig(b.build, InjectFileSystem(b.fs), InjectTempRoot(b.root))
|
||||||
}
|
}
|
||||||
@ -101,19 +112,19 @@ func (b *Builder) build() ([]byte, error) {
|
|||||||
// Set current context to clustername if it was provided
|
// Set current context to clustername if it was provided
|
||||||
var result *api.Config
|
var result *api.Config
|
||||||
var err error
|
var err error
|
||||||
var kubeContext string
|
if !b.siteWide {
|
||||||
if b.clusterName != "" {
|
var kubeContext string
|
||||||
kubeContext, result, err = b.buildOne(b.clusterName)
|
kubeContext, result, err = b.buildOne(b.clusterName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
b.siteKubeconf.CurrentContext = kubeContext
|
||||||
} else {
|
} else {
|
||||||
result, err = b.builtSiteKubeconf()
|
result, err = b.builtSiteKubeconf()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.siteKubeconf.CurrentContext = kubeContext
|
|
||||||
return clientcmd.Write(*result)
|
return clientcmd.Write(*result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ func TestBuilderClusterctl(t *testing.T) {
|
|||||||
errString string
|
errString string
|
||||||
requestedClusterName string
|
requestedClusterName string
|
||||||
tempRoot string
|
tempRoot string
|
||||||
|
siteWide bool
|
||||||
|
|
||||||
expectedContexts, expectedClusters, expectedAuthInfos []string
|
expectedContexts, expectedClusters, expectedAuthInfos []string
|
||||||
clusterMap clustermap.ClusterMap
|
clusterMap clustermap.ClusterMap
|
||||||
@ -106,6 +107,7 @@ func TestBuilderClusterctl(t *testing.T) {
|
|||||||
expectedContexts: []string{parentClusterID},
|
expectedContexts: []string{parentClusterID},
|
||||||
expectedClusters: []string{parentParentCluster},
|
expectedClusters: []string{parentParentCluster},
|
||||||
expectedAuthInfos: []string{parentParentUser},
|
expectedAuthInfos: []string{parentParentUser},
|
||||||
|
siteWide: true,
|
||||||
clusterMap: clustermap.NewClusterMap(&v1alpha1.ClusterMap{
|
clusterMap: clustermap.NewClusterMap(&v1alpha1.ClusterMap{
|
||||||
Map: map[string]*v1alpha1.Cluster{
|
Map: map[string]*v1alpha1.Cluster{
|
||||||
childClusterID: {
|
childClusterID: {
|
||||||
@ -134,6 +136,7 @@ func TestBuilderClusterctl(t *testing.T) {
|
|||||||
expectedContexts: []string{parentClusterID, parentParentClusterID},
|
expectedContexts: []string{parentClusterID, parentParentClusterID},
|
||||||
expectedClusters: []string{"dummycluster_ephemeral", parentParentCluster},
|
expectedClusters: []string{"dummycluster_ephemeral", parentParentCluster},
|
||||||
expectedAuthInfos: []string{"kubernetes-admin", parentParentUser},
|
expectedAuthInfos: []string{"kubernetes-admin", parentParentUser},
|
||||||
|
siteWide: true,
|
||||||
clusterMap: clustermap.NewClusterMap(&v1alpha1.ClusterMap{
|
clusterMap: clustermap.NewClusterMap(&v1alpha1.ClusterMap{
|
||||||
Map: map[string]*v1alpha1.Cluster{
|
Map: map[string]*v1alpha1.Cluster{
|
||||||
parentParentClusterID: {
|
parentParentClusterID: {
|
||||||
@ -165,6 +168,7 @@ func TestBuilderClusterctl(t *testing.T) {
|
|||||||
expectedContexts: []string{parentClusterID, childClusterID, parentParentClusterID},
|
expectedContexts: []string{parentClusterID, childClusterID, parentParentClusterID},
|
||||||
expectedClusters: []string{parentCluster, parentParentCluster, childCluster},
|
expectedClusters: []string{parentCluster, parentParentCluster, childCluster},
|
||||||
expectedAuthInfos: []string{parentUser, parentParentUser, childUser},
|
expectedAuthInfos: []string{parentUser, parentParentUser, childUser},
|
||||||
|
siteWide: true,
|
||||||
clusterMap: clustermap.NewClusterMap(&v1alpha1.ClusterMap{
|
clusterMap: clustermap.NewClusterMap(&v1alpha1.ClusterMap{
|
||||||
Map: map[string]*v1alpha1.Cluster{
|
Map: map[string]*v1alpha1.Cluster{
|
||||||
childClusterID: {
|
childClusterID: {
|
||||||
@ -265,6 +269,7 @@ func TestBuilderClusterctl(t *testing.T) {
|
|||||||
WithTempRoot(tt.tempRoot).
|
WithTempRoot(tt.tempRoot).
|
||||||
WithClusterctlClient(tt.clusterctlClient).
|
WithClusterctlClient(tt.clusterctlClient).
|
||||||
WithFilesystem(tt.fs).
|
WithFilesystem(tt.fs).
|
||||||
|
SiteWide(tt.siteWide).
|
||||||
Build()
|
Build()
|
||||||
require.NotNil(t, kube)
|
require.NotNil(t, kube)
|
||||||
filePath, cleanup, err := kube.GetFile()
|
filePath, cleanup, err := kube.GetFile()
|
||||||
|
@ -114,6 +114,8 @@ func (p *phase) executor(docFactory document.DocFactoryFunc,
|
|||||||
WithClusterMap(cMap).
|
WithClusterMap(cMap).
|
||||||
WithTempRoot(p.helper.WorkDir()).
|
WithTempRoot(p.helper.WorkDir()).
|
||||||
WithClusterctlClient(cctlClient).
|
WithClusterctlClient(cctlClient).
|
||||||
|
WithClusterName(p.apiObj.ClusterName).
|
||||||
|
SiteWide(p.apiObj.Config.SiteWideKubeconfig).
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
return executorFactory(
|
return executorFactory(
|
||||||
|
@ -437,6 +437,7 @@ func TestPlanRunCommand(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
factory config.Factory
|
factory config.Factory
|
||||||
expectedErr string
|
expectedErr string
|
||||||
|
planID ifc.ID
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Error config factory",
|
name: "Error config factory",
|
||||||
@ -456,7 +457,10 @@ func TestPlanRunCommand(t *testing.T) {
|
|||||||
expectedErr: "missing configuration: context with name 'does not exist'",
|
expectedErr: "missing configuration: context with name 'does not exist'",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Error phase by id",
|
name: "Error plan by id",
|
||||||
|
planID: ifc.ID{
|
||||||
|
Name: "doesn't exist",
|
||||||
|
},
|
||||||
factory: func() (*config.Config, error) {
|
factory: func() (*config.Config, error) {
|
||||||
conf := config.NewConfig()
|
conf := config.NewConfig()
|
||||||
conf.Manifests = map[string]*config.Manifest{
|
conf.Manifests = map[string]*config.Manifest{
|
||||||
@ -479,7 +483,7 @@ func TestPlanRunCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
return conf, nil
|
return conf, nil
|
||||||
},
|
},
|
||||||
expectedErr: `context "ephemeral-cluster" does not exist`,
|
expectedErr: `found no documents`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@ -490,6 +494,7 @@ func TestPlanRunCommand(t *testing.T) {
|
|||||||
GenericRunFlags: phase.GenericRunFlags{
|
GenericRunFlags: phase.GenericRunFlags{
|
||||||
DryRun: true,
|
DryRun: true,
|
||||||
},
|
},
|
||||||
|
PlanID: tt.planID,
|
||||||
},
|
},
|
||||||
Factory: tt.factory,
|
Factory: tt.factory,
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,7 @@ func (c *ContainerExecutor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
|
|||||||
cleanup, err := c.SetKubeConfig()
|
cleanup, err := c.SetKubeConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(evtCh, err)
|
handleError(evtCh, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user