diff --git a/cmd/cloud.go b/cmd/cloud.go index 9b7a0d26..54bcc922 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -50,6 +50,12 @@ var Clouds = []CloudInfo{ HomePage: "https://console.aws.amazon.com/eks/home", Service: "EKS", }, + { + Name: "Azure", + Alias: []string{"azure", "aks"}, + HomePage: "https://portal.azure.com", + Service: "AKS", + }, } // Init CloudCommand @@ -138,6 +144,28 @@ func getClusters(provider, regionID string, num int) ([]cloud.ClusterInfo, error if err != nil { return nil, err } + case 4: + fmt.Println("⛅ Selected: Azure") + clientID, clientSecret := checkEnvForSecret(4) + SubscriptionID, sub := os.LookupEnv("AZURE_SUBSCRIPTION_ID") + ObjectID, obj := os.LookupEnv("AZURE_OBJECT_ID") + TenantID, ten := os.LookupEnv("AZURE_TENANT_ID") + if !sub || !obj || !ten { + SubscriptionID = PromptUI("Azure Subscription ID", "") + ObjectID = PromptUI("Azure Object ID", "") + TenantID = PromptUI("Azure Tenant ID", "") + } + azure := cloud.Azure{ + ClientID: clientID, + ClientSecret: clientSecret, + SubscriptionID: SubscriptionID, + ObjectID: ObjectID, + TenantID: TenantID, + } + clusters, err = azure.ListCluster() + if err != nil { + return nil, err + } } return clusters, err } @@ -176,6 +204,14 @@ func checkEnvForSecret(num int) (string, string) { accessKeySecret = PromptUI("AWS Access Key Secret", "") } return accessKeyID, accessKeySecret + case 4: + accessKeyID, id := os.LookupEnv("AZURE_CLIENT_ID") + accessKeySecret, key := os.LookupEnv("AZURE_CLIENT_SECRET") + if !id || !key { + accessKeyID = PromptUI("Azure Client ID", "") + accessKeySecret = PromptUI("Azure Client Secret", "") + } + return accessKeyID, accessKeySecret } return "", "" } diff --git a/cmd/cloud_add.go b/cmd/cloud_add.go index 02abe634..64346dbc 100644 --- a/cmd/cloud_add.go +++ b/cmd/cloud_add.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "fmt" + "os" "github.com/mgutz/ansi" @@ -224,6 +225,44 @@ func (ca *CloudAddCommand) runCloudAdd(cmd *cobra.Command, args []string) error fmt.Printf("%s: %s\n", ansi.Color("Note", "blue"), ansi.Color(" please install the AWS CLI before normal use.", "white+h")) + case 4: + fmt.Println("⛅ Selected: Azure") + clientID, clientSecret := checkEnvForSecret(4) + SubscriptionID, sub := os.LookupEnv("AZURE_SUBSCRIPTION_ID") + ObjectID, obj := os.LookupEnv("AZURE_OBJECT_ID") + TenantID, ten := os.LookupEnv("AZURE_TENANT_ID") + if !sub || !obj || !ten { + SubscriptionID = PromptUI("Azure Subscription ID", "") + ObjectID = PromptUI("Azure Object ID", "") + TenantID = PromptUI("Azure Tenant ID", "") + } + azure := cloud.Azure{ + ClientID: clientID, + ClientSecret: clientSecret, + SubscriptionID: SubscriptionID, + ObjectID: ObjectID, + TenantID: TenantID, + } + if clusterID == "" { + clusters, err := azure.ListCluster() + if err != nil { + return err + } + if len(clusters) == 0 { + return errors.New("no clusters found") + } + clusterNum := selectCluster(clusters, "Select Cluster") + kubeConfig, err := azure.GetKubeConfig(clusters[clusterNum].Name, clusters[clusterNum].ID) + if err != nil { + return err + } + newConfig, err := clientcmd.Load(kubeConfig) + if err != nil { + return err + } + return AddToLocal(newConfig, fmt.Sprintf("azure-%s", clusterID), "", cover) + } + } return nil } @@ -252,6 +291,13 @@ export RANCHER_API_KEY=YOUR_API_KEY export AWS_ACCESS_KEY_ID=YOUR_AKID export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY +# Set env Azure secret key +export AZURE_SUBSCRIPTION_ID=YOUR_SUBSCRIPTION_ID +export AZURE_CLIENT_ID=YOUR_CLIENT_ID +export AZURE_CLIENT_SECRET=YOUR_CLIENT_SECRET +export AZURE_TENANT_ID=YOUR_TENANT_ID +export AZURE_OBJECT_ID=YOUR_OBJECT_ID + # Interaction: select kubeconfig from the cloud kubecm cloud add # Add kubeconfig from cloud diff --git a/docs/en-us/cli/kubecm_cloud_add.md b/docs/en-us/cli/kubecm_cloud_add.md index c826f3e6..7431af83 100644 --- a/docs/en-us/cli/kubecm_cloud_add.md +++ b/docs/en-us/cli/kubecm_cloud_add.md @@ -32,9 +32,17 @@ export RANCHER_SERVER_URL=https://xxx export RANCHER_API_KEY=YOUR_API_KEY # Set env AWS secret key +# Note: Please install the AWS CLI before normal use. export AWS_ACCESS_KEY_ID=YOUR_AKID export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY +# Set env Azure secret key +export AZURE_SUBSCRIPTION_ID=YOUR_SUBSCRIPTION_ID +export AZURE_CLIENT_ID=YOUR_CLIENT_ID +export AZURE_CLIENT_SECRET=YOUR_CLIENT_SECRET +export AZURE_TENANT_ID=YOUR_TENANT_ID +export AZURE_OBJECT_ID=YOUR_OBJECT_ID + # Interaction: select kubeconfig from the cloud kubecm cloud add # Add kubeconfig from cloud diff --git a/docs/zh-cn/cli/kubecm_cloud_add.md b/docs/zh-cn/cli/kubecm_cloud_add.md index 0758fad9..2db1fb63 100644 --- a/docs/zh-cn/cli/kubecm_cloud_add.md +++ b/docs/zh-cn/cli/kubecm_cloud_add.md @@ -32,9 +32,17 @@ export RANCHER_SERVER_URL=https://xxx export RANCHER_API_KEY=YOUR_API_KEY # Set env AWS secret key +# Note: Please install the AWS CLI before normal use. export AWS_ACCESS_KEY_ID=YOUR_AKID export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY +# Set env Azure secret key +export AZURE_SUBSCRIPTION_ID=YOUR_SUBSCRIPTION_ID +export AZURE_CLIENT_ID=YOUR_CLIENT_ID +export AZURE_CLIENT_SECRET=YOUR_CLIENT_SECRET +export AZURE_TENANT_ID=YOUR_TENANT_ID +export AZURE_OBJECT_ID=YOUR_OBJECT_ID + # Interaction: select kubeconfig from the cloud kubecm cloud add # Add kubeconfig from cloud diff --git a/go.mod b/go.mod index c91d0a42..919846b5 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,8 @@ require ( ) require ( + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible + github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/aws/aws-sdk-go v1.44.292 github.com/stretchr/testify v1.8.4 ) @@ -35,6 +37,15 @@ require ( atomicgo.dev/cursor v0.1.1 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.0.2 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.24 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect + github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect @@ -47,6 +58,7 @@ require ( github.com/containerd/console v1.0.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/ghodss/yaml v1.0.0 // indirect @@ -55,6 +67,7 @@ require ( github.com/go-openapi/jsonreference v0.20.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect @@ -76,6 +89,7 @@ require ( github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -89,6 +103,7 @@ require ( github.com/tjfoc/gmsm v1.3.2 // indirect github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect diff --git a/go.sum b/go.sum index 23d58c77..90ac80a3 100644 --- a/go.sum +++ b/go.sum @@ -39,14 +39,38 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= +github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= @@ -166,6 +190,8 @@ github.com/daviddengcn/go-colortext v1.0.0 h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -275,6 +301,10 @@ github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -471,6 +501,7 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -693,6 +724,9 @@ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -775,6 +809,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= @@ -848,6 +883,7 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -875,6 +911,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= diff --git a/pkg/cloud/azure.go b/pkg/cloud/azure.go new file mode 100644 index 00000000..95e58929 --- /dev/null +++ b/pkg/cloud/azure.go @@ -0,0 +1,90 @@ +package cloud + +import ( + "context" + "fmt" + "strings" + + "github.com/Azure/azure-sdk-for-go/profiles/latest/containerservice/mgmt/containerservice" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure/auth" +) + +// Azure struct of azure cloud +type Azure struct { + ClientID string + ClientSecret string + SubscriptionID string + TenantID string + ObjectID string +} + +func getAzureClient(clientID, clientSecret, TenantID string) (autorest.Authorizer, error) { + credConfig := auth.NewClientCredentialsConfig(clientID, clientSecret, TenantID) + return credConfig.Authorizer() +} + +// ListCluster list cluster info +func (a *Azure) ListCluster() (clusters []ClusterInfo, err error) { + authorizer, err := getAzureClient(a.ClientID, a.ClientSecret, a.TenantID) + if err != nil { + return nil, err + } + + aksClient := containerservice.NewManagedClustersClient(a.SubscriptionID) + aksClient.Authorizer = authorizer + list, err := aksClient.List(context.Background()) + if err != nil { + return nil, err + } + var clusterList []ClusterInfo + for _, cluster := range list.Values() { + clusterList = append(clusterList, ClusterInfo{ + Name: *cluster.Name, + ID: getResourceGroupName(*cluster.ID), + RegionID: *cluster.Location, + K8sVersion: *cluster.ManagedClusterProperties.KubernetesVersion, + ConsoleURL: "https://portal.azure.com", + }) + } + return clusterList, err +} + +// GetKubeConfig get kubeConfig file +func (a *Azure) GetKubeConfig(clusterName, resourceGroupName string) ([]byte, error) { + authorizer, err := getAzureClient(a.ClientID, a.ClientSecret, a.TenantID) + if err != nil { + return nil, err + } + + aksClient := containerservice.NewManagedClustersClient(a.SubscriptionID) + aksClient.Authorizer = authorizer + res, err := aksClient.ListClusterAdminCredentials(context.Background(), resourceGroupName, clusterName, "") + if err != nil { + return nil, err + } + kubeconfig := *(res.Kubeconfigs) + for _, v := range kubeconfig { + return (*(v.Value)), nil + } + return nil, nil +} + +func getResourceGroupName(id string) string { + segments := strings.Split(id, "/") + resourceGroupIndex := -1 + + for i, segment := range segments { + if segment == "resourcegroups" { + resourceGroupIndex = i + break + } + } + + if resourceGroupIndex != -1 && resourceGroupIndex+1 < len(segments) { + resourceGroupName := segments[resourceGroupIndex+1] + return resourceGroupName + } + fmt.Println("can not found resourcegroups") + return "" +}