github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cloud/iks/registry.go (about) 1 package iks 2 3 import ( 4 b64 "encoding/base64" 5 "encoding/json" 6 "fmt" 7 gohttp "net/http" 8 "net/url" 9 "strconv" 10 11 "github.com/jenkins-x/jx-logging/pkg/log" 12 13 ibmcloud "github.com/IBM-Cloud/bluemix-go" 14 "github.com/IBM-Cloud/bluemix-go/authentication" 15 "github.com/IBM-Cloud/bluemix-go/bmxerror" 16 "github.com/IBM-Cloud/bluemix-go/client" 17 "github.com/IBM-Cloud/bluemix-go/http" 18 "github.com/IBM-Cloud/bluemix-go/rest" 19 "github.com/IBM-Cloud/bluemix-go/session" 20 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 "k8s.io/client-go/kubernetes" 22 ) 23 24 type Config struct { 25 Auths map[string]*Auth `json:"auths,omitempty"` 26 } 27 28 type Auth struct { 29 Auth string `json:"auth,omitempty"` 30 } 31 32 type RegistryServiceAPI interface { 33 Registry() Registry 34 } 35 36 //MccpService holds the client 37 type registry struct { 38 *client.Client 39 } 40 41 type AddTokenResponse struct { 42 Token string `json:"token"` 43 } 44 45 type Registry interface { 46 AddToken(account string, description string, permanent bool, write bool) (string, error) 47 } 48 49 var regionToEndpoint = map[string]string{ 50 "us-south": "https://registry.ng.bluemix.net", 51 "us-east": "https://registry.ng.bluemix.net", 52 "global": "https://registry.bluemix.net", 53 "eu-gb": "https://registry.eu-gb.bluemix.net", 54 "au-syd": "https://registry.au-syd.bluemix.net", 55 "eu-de": "https://registry.eu-de.bluemix.net", 56 } 57 58 const ( 59 ErrCodeNotAuthorized = "NotAuthorized" 60 ErrCodeUnableToAuthenticate = "UnableToAuthenticate" 61 ) 62 63 func (a *registry) Registry() Registry { 64 return newRegistryAPI(a.Client) 65 } 66 67 func newRegistryAPI(c *client.Client) Registry { 68 return ®istry{ 69 Client: c, 70 } 71 } 72 73 // Try to use the regional registry used by the cluster 74 // We will also set the corresponding secret for jenkins-x right away 75 func GetClusterRegistry(kubeClient kubernetes.Interface) string { 76 77 registry := "registry.bluemix.net" // default to global 78 secretFromConfig, err := kubeClient.CoreV1().Secrets("default").Get("bluemix-default-secret-regional", metav1.GetOptions{}) 79 if err != nil { 80 return "" 81 } 82 dockerConfig := &Config{} 83 err = json.Unmarshal(secretFromConfig.Data[".dockerconfigjson"], dockerConfig) 84 if err == nil { 85 for k := range dockerConfig.Auths { 86 registry = k 87 } 88 } 89 return registry 90 } 91 92 func GetRegistryConfigJSON(registry string) (string, error) { 93 94 //token := 95 c := new(ibmcloud.Config) 96 accountID, err := ConfigFromJSON(c) 97 if err != nil { 98 return "", err 99 } 100 101 s, err := session.New(c) 102 if err != nil { 103 return "", err 104 } 105 106 registryAPI, err := NewRegistryServiceAPI(s) 107 registryIF := registryAPI.Registry() 108 clusterName, _ := GetClusterName() 109 token, err := registryIF.AddToken(accountID, fmt.Sprintf("%s Jenkins-X Token", clusterName), true, true) 110 if err != nil { 111 return "", err 112 } 113 114 newSecret := &Auth{} 115 dockerConfig := &Config{} 116 newSecret.Auth = b64.StdEncoding.EncodeToString([]byte("token:" + token)) 117 if dockerConfig.Auths == nil { 118 dockerConfig.Auths = map[string]*Auth{} 119 } 120 dockerConfig.Auths[registry] = newSecret 121 122 configBytes, err := json.Marshal(dockerConfig) 123 if err != nil { 124 return "", err 125 } 126 return string(configBytes), nil 127 } 128 129 //New ... 130 func NewRegistryServiceAPI(sess *session.Session) (RegistryServiceAPI, error) { 131 config := sess.Config.Copy() 132 if config.HTTPClient == nil { 133 config.HTTPClient = http.NewHTTPClient(config) 134 } 135 tokenRefreher, err := authentication.NewIAMAuthRepository(config, &rest.Client{ 136 DefaultHeader: gohttp.Header{ 137 "User-Agent": []string{http.UserAgent()}, 138 }, 139 HTTPClient: config.HTTPClient, 140 }) 141 if err != nil { 142 return nil, err 143 } 144 if config.IAMAccessToken == "" { 145 err := authentication.PopulateTokens(tokenRefreher, config) 146 if err != nil { 147 return nil, err 148 } 149 } 150 if config.Endpoint == nil { 151 endpoint := regionToEndpoint[config.Region] 152 config.Endpoint = &endpoint 153 } 154 155 return ®istry{ 156 Client: client.New(config, ibmcloud.IAMService, tokenRefreher), 157 }, nil 158 } 159 160 func (a *registry) AddToken(accountID string, description string, permanent bool, write bool) (string, error) { 161 queryResp := AddTokenResponse{} 162 v := url.Values{} 163 v.Set("description", description) 164 v.Set("permanent", strconv.FormatBool(permanent)) 165 v.Set("write", strconv.FormatBool(write)) 166 m := make(map[string]string, 1) 167 m["Account"] = accountID 168 169 response, err := a.Client.Post(fmt.Sprintf("/api/v1/tokens?%s", v.Encode()), nil, &queryResp, m) 170 if err != nil { 171 log.Logger().Errorf("error - %s", err) 172 if response.StatusCode == 401 { 173 return "", bmxerror.New(ErrCodeNotAuthorized, 174 "You are not authorized to view the requested resource, or your IBM Cloud bearer token is invalid. Correct the request and try again.") 175 } 176 if response.StatusCode == 503 { 177 return "", bmxerror.New(ErrCodeUnableToAuthenticate, 178 "Unable to authenticate with IBM Cloud. Try again later.") 179 } 180 return "", err 181 182 } 183 return queryResp.Token, nil 184 185 }