| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package aws
- import (
- "fmt"
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/utils"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/cloudmux/pkg/multicloud"
- )
- type SKubeCluster struct {
- multicloud.SResourceBase
- AwsTags
- region *SRegion
- Name string
- Arn string `json:"arn"`
- CreatedAt float64 `json:"createdAt"`
- Version string `json:"version"`
- Endpoint string `json:"endpoint"`
- RoleArn string `json:"roleArn"`
- ResourcesVpcConfig struct {
- SubnetIds []string `json:"subnetIds"`
- SecurityGroupIds []string `json:"securityGroupIds"`
- ClusterSecurityGroupId string `json:"clusterSecurityGroupId"`
- VpcId string `json:"vpcId"`
- EndpointPublicAccess bool `json:"endpointPublicAccess"`
- EndpointPrivateAccess bool `json:"endpointPrivateAccess"`
- PublicAccessCidrs []string `json:"publicAccessCidrs"`
- } `json:"resourcesVpcConfig"`
- KubernetesNetworkConfig struct {
- ServiceIpv4CIDR string `json:"serviceIpv4Cidr"`
- ServiceIpv6CIDR string `json:"serviceIpv6Cidr"`
- IPFamily string `json:"ipFamily"`
- } `json:"kubernetesNetworkConfig"`
- Logging struct {
- ClusterLogging []ClusterLogging `json:"clusterLogging"`
- } `json:"logging"`
- Identity string `json:"identity"`
- Status string `json:"status"`
- CertificateAuthority struct {
- Data string
- } `json:"certificateAuthority"`
- ClientRequestToken string `json:"clientRequestToken"`
- PlatformVersion string `json:"platformVersion"`
- EncryptionConfig string `json:"encryptionConfig"`
- ConnectorConfig string `json:"connectorConfig"`
- Id string `json:"id"`
- Health string `json:"health"`
- }
- type ClusterLogging struct {
- Types []string `json:"types"`
- Enabled bool `json:"enabled"`
- }
- func (self *SKubeCluster) GetName() string {
- return self.Name
- }
- func (self *SKubeCluster) GetId() string {
- return self.Name
- }
- func (self *SKubeCluster) GetGlobalId() string {
- return self.GetId()
- }
- func (self *SKubeCluster) GetEnabled() bool {
- return true
- }
- func (self *SKubeCluster) GetStatus() string {
- if len(self.Status) == 0 {
- self.Refresh()
- }
- switch self.Status {
- case "ACTIVE":
- return api.KUBE_CLUSTER_STATUS_RUNNING
- case "DELETING":
- return api.KUBE_CLUSTER_STATUS_DELETING
- default:
- return strings.ToLower(self.Status)
- }
- }
- func (self *SKubeCluster) GetKubeConfig(private bool, expireMinutes int) (*cloudprovider.SKubeconfig, error) {
- if len(self.CertificateAuthority.Data) == 0 {
- self.Refresh()
- }
- eksId := fmt.Sprintf("%s:%s:cluster/%s", self.region.RegionId, self.region.client.ownerId, self.Name)
- config := fmt.Sprintf(`apiVersion: v1
- clusters:
- - cluster:
- server: %s
- certificate-authority-data: %s
- name: arn:aws:eks:%s
- contexts:
- - context:
- cluster: arn:aws:eks:%s
- user: arn:aws:eks:%s
- name: arn:aws:eks:%s
- current-context: arn:aws:eks:%s
- kind: Config
- preferences: {}
- users:
- - name: arn:aws:eks:%s
- user:
- exec:
- apiVersion: client.authentication.k8s.io/v1beta1
- command: aws-iam-authenticator
- args:
- - "token"
- - "-i"
- - "%s"`, self.Endpoint, self.CertificateAuthority.Data, eksId, eksId, eksId, eksId, eksId, eksId, self.Name)
- return &cloudprovider.SKubeconfig{
- Config: config,
- }, nil
- }
- func (self *SKubeCluster) GetIKubeNodePools() ([]cloudprovider.ICloudKubeNodePool, error) {
- ret := []cloudprovider.ICloudKubeNodePool{}
- nextToken := ""
- for {
- part, nextToken, err := self.region.GetNodegroups(self.Name, nextToken)
- if err != nil {
- return nil, errors.Wrapf(err, "GetNodegroups")
- }
- for i := range part {
- ret = append(ret, &part[i])
- }
- if len(nextToken) == 0 {
- break
- }
- }
- return ret, nil
- }
- func (self *SKubeCluster) GetIKubeNodes() ([]cloudprovider.ICloudKubeNode, error) {
- return nil, cloudprovider.ErrNotImplemented
- }
- func (self *SKubeCluster) Delete(isRetain bool) error {
- return self.region.DeleteKubeCluster(self.Name)
- }
- func (self *SKubeCluster) GetCreatedAt() time.Time {
- return time.Unix(int64(self.CreatedAt), 0)
- }
- func (self *SKubeCluster) GetVpcId() string {
- if len(self.ResourcesVpcConfig.VpcId) == 0 {
- self.Refresh()
- }
- return self.ResourcesVpcConfig.VpcId
- }
- func (self *SKubeCluster) GetVersion() string {
- if len(self.Version) == 0 {
- self.Refresh()
- }
- return self.Version
- }
- func (self *SKubeCluster) GetNetworkIds() []string {
- if len(self.ResourcesVpcConfig.SubnetIds) == 0 {
- self.Refresh()
- }
- return self.ResourcesVpcConfig.SubnetIds
- }
- func (self *SKubeCluster) Refresh() error {
- cluster, err := self.region.GetKubeCluster(self.Name)
- if err != nil {
- return err
- }
- return jsonutils.Update(self, cluster)
- }
- func (self *SRegion) GetKubeClusters(nextToken string) ([]SKubeCluster, string, error) {
- ret := struct {
- Clusters []string
- NextToken string
- }{}
- params := map[string]interface{}{
- "include": "all",
- }
- if len(nextToken) > 0 {
- params["nextToken"] = nextToken
- }
- result := []SKubeCluster{}
- err := self.eksRequest("ListClusters", "/clusters", params, &ret)
- if err != nil {
- return nil, "", errors.Wrapf(err, "ListClusters")
- }
- for i := range ret.Clusters {
- result = append(result, SKubeCluster{
- region: self,
- Name: ret.Clusters[i],
- })
- }
- return result, ret.NextToken, nil
- }
- func (self *SRegion) GetKubeCluster(name string) (*SKubeCluster, error) {
- params := map[string]interface{}{
- "name": name,
- }
- ret := struct {
- Cluster SKubeCluster
- }{}
- err := self.eksRequest("DescribeCluster", "/clusters/{name}", params, &ret)
- if err != nil {
- return nil, errors.Wrapf(err, "DescribeCluster")
- }
- ret.Cluster.region = self
- return &ret.Cluster, nil
- }
- func (self *SRegion) DeleteKubeCluster(name string) error {
- params := map[string]interface{}{
- "name": name,
- }
- ret := struct {
- }{}
- return self.eksRequest("DeleteCluster", "/clusters/{name}", params, &ret)
- }
- func (self *SRegion) GetICloudKubeClusters() ([]cloudprovider.ICloudKubeCluster, error) {
- ret := []cloudprovider.ICloudKubeCluster{}
- nextToken := ""
- for {
- part, nextToken, err := self.GetKubeClusters(nextToken)
- if err != nil {
- return nil, errors.Wrapf(err, "GetKubeClusters")
- }
- for i := range part {
- part[i].region = self
- ret = append(ret, &part[i])
- }
- if len(nextToken) == 0 {
- break
- }
- }
- return ret, nil
- }
- func (self *SRegion) GetICloudKubeClusterById(id string) (cloudprovider.ICloudKubeCluster, error) {
- cluster, err := self.GetKubeCluster(id)
- if err != nil {
- return nil, err
- }
- return cluster, nil
- }
- func (self *SRegion) CreateIKubeCluster(opts *cloudprovider.KubeClusterCreateOptions) (cloudprovider.ICloudKubeCluster, error) {
- cluster, err := self.CreateKubeCluster(opts)
- if err != nil {
- return nil, err
- }
- return cluster, nil
- }
- func (self *SRegion) CreateKubeCluster(opts *cloudprovider.KubeClusterCreateOptions) (*SKubeCluster, error) {
- if !opts.PrivateAccess && !opts.PublicAccess { // avoid occur 'Private and public endpoint access cannot be false' error
- opts.PrivateAccess = true
- }
- params := map[string]interface{}{
- "name": opts.NAME,
- "clientRequestToken": utils.GenRequestId(20),
- "resourcesVpcConfig": map[string]interface{}{
- "endpointPrivateAccess": opts.PrivateAccess,
- "endpointPublicAccess": opts.PublicAccess,
- "subnetIds": opts.NetworkIds,
- },
- "tags": opts.Tags,
- }
- if len(opts.RoleName) == 0 {
- opts.RoleName = "eksClusterRole"
- }
- role, err := func() (*SRole, error) {
- role, err := self.client.GetRole(opts.RoleName)
- if err != nil {
- if errors.Cause(err) == cloudprovider.ErrNotFound {
- params := map[string]string{
- "RoleName": opts.RoleName,
- "Description": opts.Desc,
- "AssumeRolePolicyDocument": k8sRole,
- }
- role := struct {
- Role SRole
- }{}
- err := self.client.iamRequest("CreateRole", params, &role)
- if err != nil {
- return nil, errors.Wrapf(err, "CreateRole")
- }
- role.Role.client = self.client
- return &role.Role, nil
- }
- return nil, errors.Wrapf(err, "GetRole(%s)", opts.RoleName)
- }
- return role, nil
- }()
- if err != nil {
- return nil, err
- }
- err = self.client.AttachRolePolicy(opts.RoleName, self.client.getIamArn("AmazonEKSClusterPolicy"))
- if err != nil {
- return nil, errors.Wrapf(err, "AttachRolePolicy")
- }
- params["roleArn"] = role.Arn
- if len(opts.ServiceCIDR) > 0 {
- params["kubernetesNetworkConfig"] = map[string]interface{}{
- "ipFamily": "ipv4",
- "serviceIpv4Cidr": opts.ServiceCIDR,
- }
- }
- if len(opts.Version) > 0 {
- params["version"] = opts.Version
- }
- ret := struct {
- Cluster SKubeCluster
- }{}
- err = self.eksRequest("CreateCluster", "/clusters", params, &ret)
- if err != nil {
- return nil, err
- }
- ret.Cluster.region = self
- return &ret.Cluster, nil
- }
- func (self *SRegion) CreateNodegroup(cluster string, opts *cloudprovider.KubeNodePoolCreateOptions) (*SNodeGroup, error) {
- params := map[string]interface{}{
- "nodegroupName": opts.NAME,
- "clientRequestToken": utils.GenRequestId(20),
- "diskSize": opts.RootDiskSizeGb,
- "instanceTypes": opts.InstanceTypes,
- "tags": opts.Tags,
- "scalingConfig": map[string]interface{}{
- "desiredSize": opts.DesiredInstanceCount,
- "maxSize": opts.MaxInstanceCount,
- "minSize": opts.MinInstanceCount,
- },
- "subnets": opts.NetworkIds,
- }
- if len(opts.PublicKey) > 0 {
- keypairName, err := self.SyncKeypair(opts.PublicKey)
- if err != nil {
- return nil, errors.Wrapf(err, "syncKeypair")
- }
- params["remoteAccess"] = map[string]string{
- "ec2SshKey": keypairName,
- }
- }
- roleName := "AmazonEKSNodeRole"
- role, err := func() (*SRole, error) {
- role, err := self.client.GetRole(roleName)
- if err != nil {
- if errors.Cause(err) == cloudprovider.ErrNotFound {
- params := map[string]string{
- "RoleName": roleName,
- "Description": opts.Desc,
- "AssumeRolePolicyDocument": nodeRole,
- }
- role := struct {
- Role SRole
- }{}
- err := self.client.iamRequest("CreateRole", params, &role)
- if err != nil {
- return nil, errors.Wrapf(err, "CreateRole")
- }
- role.Role.client = self.client
- return &role.Role, nil
- }
- return nil, errors.Wrapf(err, "GetRole(%s)", roleName)
- }
- return role, nil
- }()
- if err != nil {
- return nil, errors.Wrapf(err, "Create role")
- }
- for _, policy := range []string{"AmazonEKSWorkerNodePolicy", "AmazonEC2ContainerRegistryReadOnly"} {
- err = self.client.AttachRolePolicy(roleName, self.client.getIamArn(policy))
- if err != nil {
- return nil, errors.Wrapf(err, "AttachRolePolicy %s", policy)
- }
- }
- params["nodeRole"] = role.Arn
- ret := struct {
- Nodegroup SNodeGroup
- }{}
- err = self.eksRequest("CreateNodegroup", fmt.Sprintf("/clusters/%s/node-groups", cluster), params, &ret)
- if err != nil {
- return nil, err
- }
- ret.Nodegroup.region = self
- return &ret.Nodegroup, nil
- }
- func (self *SKubeCluster) CreateIKubeNodePool(opts *cloudprovider.KubeNodePoolCreateOptions) (cloudprovider.ICloudKubeNodePool, error) {
- nodegroup, err := self.region.CreateNodegroup(self.Name, opts)
- if err != nil {
- return nil, errors.Wrapf(err, "CreateNodegroup")
- }
- return nodegroup, nil
- }
- func (self *SKubeCluster) GetDescription() string {
- return ""
- }
|