Mount kubeconfig to GenericContainer executor
Change-Id: Ide647fc0cfd9d281d57eeeaf8b3f9c33f59e7fdf
This commit is contained in:
parent
e2af947337
commit
63e6012133
@ -27,6 +27,14 @@ const (
|
|||||||
GenericContainerTypeAirship GenericContainerType = "airship"
|
GenericContainerTypeAirship GenericContainerType = "airship"
|
||||||
// GenericContainerTypeKrm specifies that kustomize krm function will be used
|
// GenericContainerTypeKrm specifies that kustomize krm function will be used
|
||||||
GenericContainerTypeKrm GenericContainerType = "krm"
|
GenericContainerTypeKrm GenericContainerType = "krm"
|
||||||
|
// KubeConfigEnvKey uses as a key for kubeconfig env variable
|
||||||
|
KubeConfigEnvKey = "KUBECONFIG"
|
||||||
|
// KubeConfigPath is a path for mounted kubeconfig inside container
|
||||||
|
KubeConfigPath = "/kubeconfig"
|
||||||
|
// KubeConfigEnvKeyContext uses as a key for kubectl context env variable
|
||||||
|
KubeConfigEnvKeyContext = "KCTL_CONTEXT"
|
||||||
|
// KubeConfigEnv uses as a kubeconfig env variable
|
||||||
|
KubeConfigEnv = KubeConfigEnvKey + "=" + KubeConfigPath
|
||||||
)
|
)
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
|
9
pkg/container/testdata/single/cluster-map.yaml
vendored
Normal file
9
pkg/container/testdata/single/cluster-map.yaml
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
apiVersion: airshipit.org/v1alpha1
|
||||||
|
kind: ClusterMap
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
airshipit.org/deploy-k8s: "false"
|
||||||
|
name: main-map
|
||||||
|
map:
|
||||||
|
testCluster: {}
|
@ -1,2 +1,3 @@
|
|||||||
resources:
|
resources:
|
||||||
- secret.yaml
|
- secret.yaml
|
||||||
|
- cluster-map.yaml
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/pkg/document"
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
"opendev.org/airship/airshipctl/pkg/errors"
|
"opendev.org/airship/airshipctl/pkg/errors"
|
||||||
"opendev.org/airship/airshipctl/pkg/events"
|
"opendev.org/airship/airshipctl/pkg/events"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
|
||||||
"opendev.org/airship/airshipctl/pkg/log"
|
"opendev.org/airship/airshipctl/pkg/log"
|
||||||
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
||||||
)
|
)
|
||||||
@ -40,6 +41,7 @@ type ContainerExecutor struct {
|
|||||||
ExecutorBundle document.Bundle
|
ExecutorBundle document.Bundle
|
||||||
ExecutorDocument document.Document
|
ExecutorDocument document.Document
|
||||||
Helper ifc.Helper
|
Helper ifc.Helper
|
||||||
|
Options ifc.ExecutorConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContainerExecutor creates instance of phase executor
|
// NewContainerExecutor creates instance of phase executor
|
||||||
@ -70,6 +72,7 @@ func NewContainerExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) {
|
|||||||
ClientFunc: container.NewClientV1Alpha1,
|
ClientFunc: container.NewClientV1Alpha1,
|
||||||
Helper: cfg.Helper,
|
Helper: cfg.Helper,
|
||||||
Container: apiObj,
|
Container: apiObj,
|
||||||
|
Options: cfg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +85,14 @@ func (c *ContainerExecutor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
|
|||||||
Message: "starting generic container",
|
Message: "starting generic container",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if c.Options.ClusterName != "" {
|
||||||
|
cleanup, err := c.SetKubeConfig()
|
||||||
|
if err != nil {
|
||||||
|
handleError(evtCh, err)
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
input, err := bundleReader(c.ExecutorBundle)
|
input, err := bundleReader(c.ExecutorBundle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO move bundleFactory here, and make sure that if executorDoc is not defined, we dont fail
|
// TODO move bundleFactory here, and make sure that if executorDoc is not defined, we dont fail
|
||||||
@ -121,6 +132,31 @@ func (c *ContainerExecutor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetKubeConfig adds env variable and mounts kubeconfig to container
|
||||||
|
func (c *ContainerExecutor) SetKubeConfig() (kubeconfig.Cleanup, error) {
|
||||||
|
clusterMap, err := c.Helper.ClusterMap()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
context, err := clusterMap.ClusterKubeconfigContext(c.Options.ClusterName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
kubeConfigSrc, cleanup, err := c.Options.KubeConfig.GetFile()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Container.Spec.StorageMounts = append(c.Container.Spec.StorageMounts, v1alpha1.StorageMount{
|
||||||
|
MountType: "bind",
|
||||||
|
Src: kubeConfigSrc,
|
||||||
|
DstPath: v1alpha1.KubeConfigPath,
|
||||||
|
})
|
||||||
|
envs := []string{v1alpha1.KubeConfigEnv, v1alpha1.KubeConfigEnvKeyContext + "=" + context}
|
||||||
|
c.Container.Spec.EnvVars = append(c.Container.Spec.EnvVars, envs...)
|
||||||
|
|
||||||
|
return cleanup, nil
|
||||||
|
}
|
||||||
|
|
||||||
// bundleReader sets input for function
|
// bundleReader sets input for function
|
||||||
func bundleReader(bundle document.Bundle) (io.Reader, error) {
|
func bundleReader(bundle document.Bundle) (io.Reader, error) {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
@ -14,6 +14,7 @@ package executors_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -24,6 +25,7 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/pkg/container"
|
"opendev.org/airship/airshipctl/pkg/container"
|
||||||
"opendev.org/airship/airshipctl/pkg/document"
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
"opendev.org/airship/airshipctl/pkg/events"
|
"opendev.org/airship/airshipctl/pkg/events"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/k8s/kubeconfig"
|
||||||
"opendev.org/airship/airshipctl/pkg/phase/executors"
|
"opendev.org/airship/airshipctl/pkg/phase/executors"
|
||||||
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
"opendev.org/airship/airshipctl/pkg/phase/ifc"
|
||||||
)
|
)
|
||||||
@ -174,6 +176,14 @@ type: Opaque
|
|||||||
Container: tt.containerAPI,
|
Container: tt.containerAPI,
|
||||||
ClientFunc: tt.clientFunc,
|
ClientFunc: tt.clientFunc,
|
||||||
Helper: makeDefaultHelper(t, tt.targetPath, "../metadata.yaml"),
|
Helper: makeDefaultHelper(t, tt.targetPath, "../metadata.yaml"),
|
||||||
|
Options: ifc.ExecutorConfig{
|
||||||
|
ClusterName: "testCluster",
|
||||||
|
KubeConfig: fakeKubeConfig{
|
||||||
|
getFile: func() (string, kubeconfig.Cleanup, error) {
|
||||||
|
return "testPath", func() {}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan events.Event)
|
ch := make(chan events.Event)
|
||||||
@ -199,3 +209,60 @@ type: Opaque
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetKubeConfig(t *testing.T) {
|
||||||
|
getFileErr := fmt.Errorf("failed to get file")
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
opts ifc.ExecutorConfig
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Set valid kubeconfig",
|
||||||
|
opts: ifc.ExecutorConfig{
|
||||||
|
ClusterName: "testCluster",
|
||||||
|
KubeConfig: fakeKubeConfig{
|
||||||
|
getFile: func() (string, kubeconfig.Cleanup, error) {
|
||||||
|
return "testPath", func() {}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Failed to get kubeconfig file",
|
||||||
|
opts: ifc.ExecutorConfig{
|
||||||
|
ClusterName: "testCluster",
|
||||||
|
KubeConfig: fakeKubeConfig{
|
||||||
|
getFile: func() (string, kubeconfig.Cleanup, error) {
|
||||||
|
return "", func() {}, getFileErr
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: getFileErr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
tt := tc
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
e := executors.ContainerExecutor{
|
||||||
|
Options: tt.opts,
|
||||||
|
Container: &v1alpha1.GenericContainer{},
|
||||||
|
Helper: makeDefaultHelper(t, singleExecutorBundlePath, "../metadata.yaml"),
|
||||||
|
}
|
||||||
|
_, err := e.SetKubeConfig()
|
||||||
|
assert.Equal(t, tt.expectedErr, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeKubeConfig struct {
|
||||||
|
getFile func() (string, kubeconfig.Cleanup, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k fakeKubeConfig) GetFile() (string, kubeconfig.Cleanup, error) { return k.getFile() }
|
||||||
|
func (k fakeKubeConfig) Write(_ io.Writer) error { return nil }
|
||||||
|
func (k fakeKubeConfig) WriteFile(path string) error { return nil }
|
||||||
|
func (k fakeKubeConfig) WriteTempFile(dumpRoot string) (string, kubeconfig.Cleanup, error) {
|
||||||
|
return k.getFile()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user