-
-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
361 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/manifoldco/promptui" | ||
"github.com/spf13/cobra" | ||
coreV1 "k8s.io/api/core/v1" | ||
rbacV1 "k8s.io/api/rbac/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
"k8s.io/client-go/tools/clientcmd" | ||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | ||
) | ||
|
||
// ClearCommand clean command struct | ||
type CreateCommand struct { | ||
BaseCommand | ||
} | ||
|
||
type CreateOptions struct { | ||
config *clientcmdapi.Config | ||
clientSet *kubernetes.Clientset | ||
role string | ||
token string | ||
contextName string | ||
userName string | ||
namespace string | ||
} | ||
|
||
// Init AliasCommand | ||
func (ce *CreateCommand) Init() { | ||
ce.command = &cobra.Command{ | ||
Use: "create", | ||
Short: "Create new KubeConfig(experiment)", | ||
Long: "Create new KubeConfig(experiment)", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return ce.runCreate(cmd, args) | ||
}, | ||
Example: createExample(), | ||
} | ||
ce.command.DisableFlagsInUseLine = true | ||
} | ||
|
||
func (ce *CreateCommand) runCreate(cmd *cobra.Command, args []string) error { | ||
config, err := clientcmd.LoadFromFile(cfgFile) | ||
if err != nil { | ||
return err | ||
} | ||
userName := PromptUI("user name", "") | ||
co := CreateOptions{ | ||
config: config, | ||
userName: userName, | ||
} | ||
err = co.chooseContext() | ||
if err != nil { | ||
return err | ||
} | ||
err = co.chooseNamespace() | ||
if err != nil { | ||
return err | ||
} | ||
err = co.createServiceAccounts() | ||
if err != nil { | ||
return err | ||
} | ||
err = co.selectClusterRole() | ||
if err != nil { | ||
return err | ||
} | ||
err = co.createRoleBinding() | ||
if err != nil { | ||
return err | ||
} | ||
err = co.getToken() | ||
if err != nil { | ||
return err | ||
} | ||
newConfig := co.putOutKubeConfig() | ||
fileName := fmt.Sprintf("%s.kubeconfig", co.userName) | ||
err = clientcmd.WriteToFile(*newConfig, fileName) | ||
if err != nil { | ||
return err | ||
} | ||
printString(os.Stdout, "kubeconfig: "+fileName+" create success\n") | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) chooseContext() error { | ||
var kubeItems []Needle | ||
current := co.config.CurrentContext | ||
for key, obj := range co.config.Contexts { | ||
if key != current { | ||
kubeItems = append(kubeItems, Needle{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo}) | ||
} else { | ||
kubeItems = append([]Needle{{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo, Center: "(*)"}}, kubeItems...) | ||
} | ||
} | ||
num := SelectUI(kubeItems, "Select Kube Context") | ||
co.contextName = kubeItems[num].Name | ||
co.config.CurrentContext = co.contextName | ||
clientConfig := clientcmd.NewDefaultClientConfig( | ||
*co.config, | ||
&clientcmd.ConfigOverrides{}, | ||
) | ||
c, _ := clientConfig.ClientConfig() | ||
clientSet, err := kubernetes.NewForConfig(c) | ||
if err != nil { | ||
return err | ||
} | ||
co.clientSet = clientSet | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) chooseNamespace() error { | ||
var nss []Namespaces | ||
ctx := context.TODO() | ||
namespaceList, err := co.clientSet.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
for _, specItem := range namespaceList.Items { | ||
nss = append(nss, Namespaces{Name: specItem.Name, Default: false}) | ||
} | ||
num := selectNamespace(nss) | ||
co.namespace = nss[num].Name | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) createServiceAccounts() error { | ||
saName := co.userName | ||
// TODO 判断 sa 是否存在 | ||
userServiceAccount, err := co.clientSet.CoreV1().ServiceAccounts(co.namespace).Get(context.TODO(), saName, metav1.GetOptions{}) | ||
if err != nil { | ||
saObj := &coreV1.ServiceAccount{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: saName, | ||
}, | ||
} | ||
userServiceAccount, err = co.clientSet.CoreV1().ServiceAccounts(co.namespace).Create(context.TODO(), saObj, metav1.CreateOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
printString(os.Stdout, "ServiceAccount") | ||
fmt.Printf(" : %s create success\n", userServiceAccount.Name) | ||
} else { | ||
printYellow(os.Stdout, "ServiceAccount") | ||
fmt.Printf(" : %s already exists\n", userServiceAccount.Name) | ||
} | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) selectClusterRole() error { | ||
clusterRoleList := []string{ | ||
"view", "edit", "admin", "cluster-admin", "custom", | ||
} | ||
templates := &promptui.SelectTemplates{ | ||
Label: "{{ . }}", | ||
Active: "\U0001F63C {{ . | red }}", | ||
Inactive: " {{ . | cyan }}", | ||
Selected: "\U0001F638 Select:{{ . | green }}", | ||
} | ||
prompt := promptui.Select{ | ||
Label: "please select the cluster role of the user:", | ||
Items: clusterRoleList, | ||
Templates: templates, | ||
Size: 4, | ||
} | ||
i, _, err := prompt.Run() | ||
if err != nil { | ||
return err | ||
} | ||
if clusterRoleList[i] == "custom" { | ||
customClusterRole := PromptUI("custom cluster role", "") | ||
fmt.Println(customClusterRole) | ||
_, err := co.clientSet.RbacV1().ClusterRoles().Get(context.TODO(), customClusterRole, metav1.GetOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
co.role = customClusterRole | ||
} else { | ||
co.role = clusterRoleList[i] | ||
} | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) createRoleBinding() error { | ||
co.role = "view" | ||
rb := &rbacV1.RoleBinding{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: fmt.Sprintf("%s-%s", co.userName, co.role), | ||
Namespace: co.namespace, | ||
}, | ||
Subjects: []rbacV1.Subject{ | ||
{ | ||
Kind: "ServiceAccount", | ||
Name: co.userName, | ||
Namespace: co.namespace, | ||
}, | ||
}, | ||
RoleRef: rbacV1.RoleRef{ | ||
APIGroup: "rbac.authorization.k8s.io", | ||
Kind: "ClusterRole", | ||
Name: co.role, | ||
}, | ||
} | ||
newRoleBinding, err := co.clientSet.RbacV1().RoleBindings(co.namespace).Create(context.TODO(), rb, metav1.CreateOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
printString(os.Stdout, "RoleBinding") | ||
fmt.Printf(" : %s create success\n", newRoleBinding.Name) | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) getToken() error { | ||
sa, err := co.clientSet.CoreV1().ServiceAccounts(co.namespace).Get(context.TODO(), co.userName, metav1.GetOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
secretName := sa.Secrets[0].Name | ||
secretToken, _ := co.clientSet.CoreV1().Secrets(co.namespace).Get(context.TODO(), secretName, metav1.GetOptions{}) | ||
sEnc := base64.StdEncoding.EncodeToString(secretToken.Data["token"]) | ||
sDec, err := base64.StdEncoding.DecodeString(sEnc) | ||
if err != nil { | ||
return err | ||
} | ||
co.token = string(sDec) | ||
return nil | ||
} | ||
|
||
func (co *CreateOptions) putOutKubeConfig() *clientcmdapi.Config { | ||
coContext := co.config.Contexts[co.contextName] | ||
coCluster := co.config.Clusters[coContext.Cluster] | ||
coAuthInfo := clientcmdapi.NewAuthInfo() | ||
coAuthInfo.Token = co.token | ||
coContext.AuthInfo = co.userName | ||
|
||
newConfig := clientcmdapi.NewConfig() | ||
newConfig.Clusters[coContext.Cluster] = coCluster | ||
newConfig.AuthInfos[coContext.AuthInfo] = coAuthInfo | ||
newConfig.Contexts[co.userName] = coContext | ||
newConfig.CurrentContext = co.userName | ||
return newConfig | ||
} | ||
|
||
func createExample() string { | ||
return ` | ||
# Create new KubeConfig(experiment) | ||
kubecm create | ||
` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,16 @@ | ||
* [Install](/en-us/install.md) | ||
* [Interactive operation](/en-us/interactive.md) | ||
* CLI References | ||
* [kubecm add](/en-us/cli/kubecm_add.md) | ||
* [kubecm alias](/en-us/cli/kubecm_alias.md) | ||
* [kubecm completion](/en-us/cli/kubecm_completion.md) | ||
* [kubecm delete](/en-us/cli/kubecm_delete.md) | ||
* [kubecm ls](/en-us/cli/kubecm_ls.md) | ||
* [kubecm merge](/en-us/cli/kubecm_merge.md) | ||
* [kubecm namespace](/en-us/cli/kubecm_namespace.md) | ||
* [kubecm rename](/en-us/cli/kubecm_rename.md) | ||
* [kubecm switch](/en-us/cli/kubecm_switch.md) | ||
* [kubecm clear](/en-us/cli/kubecm_clear.md) | ||
* [kubecm version](/en-us/cli/kubecm_version.md) | ||
* [add](/en-us/cli/kubecm_add.md) | ||
* [create(experiment)](/en-us/cli/kubecm_create.md) | ||
* [alias](/en-us/cli/kubecm_alias.md) | ||
* [completion](/en-us/cli/kubecm_completion.md) | ||
* [delete](/en-us/cli/kubecm_delete.md) | ||
* [ls](/en-us/cli/kubecm_ls.md) | ||
* [merge](/en-us/cli/kubecm_merge.md) | ||
* [namespace](/en-us/cli/kubecm_namespace.md) | ||
* [rename](/en-us/cli/kubecm_rename.md) | ||
* [switch](/en-us/cli/kubecm_switch.md) | ||
* [clear](/en-us/cli/kubecm_clear.md) | ||
* [version](/en-us/cli/kubecm_version.md) | ||
* [Contribute](/en-us/contribute.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
## kubecm create | ||
|
||
Create new KubeConfig(experiment) | ||
|
||
### Synopsis | ||
|
||
Create new KubeConfig(experiment) | ||
|
||
``` | ||
kubecm create | ||
``` | ||
|
||
### Examples | ||
|
||
``` | ||
# Create new KubeConfig(experiment) | ||
kubecm create | ||
``` | ||
|
||
### Options | ||
|
||
``` | ||
-h, --help help for create | ||
``` | ||
|
||
### Options inherited from parent commands | ||
|
||
``` | ||
--config string path of kubeconfig (default "/Users/saybot/.kube/config") | ||
``` | ||
|
||
### SEE ALSO | ||
|
||
* [kubecm](../../../tmp/cli/kubecm.md) - KubeConfig Manager. | ||
|
||
###### Auto generated by spf13/cobra on 4-Feb-2021 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,16 @@ | ||
* [安装](/zh-cn/install.md) | ||
* [交互式操作](/zh-cn/interactive.md) | ||
* CLI 参考 | ||
* [kubecm add](/zh-cn/cli/kubecm_add.md) | ||
* [kubecm alias](/zh-cn/cli/kubecm_alias.md) | ||
* [kubecm completion](/zh-cn/cli/kubecm_completion.md) | ||
* [kubecm delete](/zh-cn/cli/kubecm_delete.md) | ||
* [kubecm ls](/zh-cn/cli/kubecm_ls.md) | ||
* [kubecm merge](/zh-cn/cli/kubecm_merge.md) | ||
* [kubecm namespace](/zh-cn/cli/kubecm_namespace.md) | ||
* [kubecm rename](/zh-cn/cli/kubecm_rename.md) | ||
* [kubecm switch](/zh-cn/cli/kubecm_switch.md) | ||
* [kubecm clear](/en-us/cli/kubecm_clear.md) | ||
* [kubecm version](/zh-cn/cli/kubecm_version.md) | ||
* [add](/zh-cn/cli/kubecm_add.md) | ||
* [create(实验性)](/zh-cn/cli/kubecm_create.md) | ||
* [alias](/zh-cn/cli/kubecm_alias.md) | ||
* [completion](/zh-cn/cli/kubecm_completion.md) | ||
* [delete](/zh-cn/cli/kubecm_delete.md) | ||
* [ls](/zh-cn/cli/kubecm_ls.md) | ||
* [merge](/zh-cn/cli/kubecm_merge.md) | ||
* [namespace](/zh-cn/cli/kubecm_namespace.md) | ||
* [rename](/zh-cn/cli/kubecm_rename.md) | ||
* [switch](/zh-cn/cli/kubecm_switch.md) | ||
* [clear](/en-us/cli/kubecm_clear.md) | ||
* [version](/zh-cn/cli/kubecm_version.md) | ||
* [贡献](/zh-cn/contribute.md) |
Oops, something went wrong.