github.com/jenkins-x/jx/v2@v2.1.155/pkg/cloud/iks/accounts.go (about) 1 package iks 2 3 // based on "github.com/IBM-Cloud/bluemix-go/account/accountv2 to add linkages 4 5 import ( 6 "fmt" 7 gohttp "net/http" 8 9 ibmcloud "github.com/IBM-Cloud/bluemix-go" 10 "github.com/IBM-Cloud/bluemix-go/api/account/accountv2" 11 "github.com/IBM-Cloud/bluemix-go/authentication" 12 "github.com/IBM-Cloud/bluemix-go/bmxerror" 13 "github.com/IBM-Cloud/bluemix-go/client" 14 "github.com/IBM-Cloud/bluemix-go/http" 15 "github.com/IBM-Cloud/bluemix-go/rest" 16 "github.com/IBM-Cloud/bluemix-go/session" 17 ) 18 19 //Metadata ... 20 type Metadata struct { 21 GUID string `json:"guid"` 22 URL string `json:"url"` 23 } 24 25 //Resource ... 26 type Resource struct { 27 Metadata Metadata 28 } 29 30 //Account Model ... 31 type Account struct { 32 GUID string 33 Name string 34 Type string 35 State string 36 OwnerGUID string 37 OwnerUserID string 38 OwnerUniqueID string 39 CustomerID string 40 CountryCode string 41 CurrencyCode string 42 Organizations []AccountOrganization 43 IMSAccountID string 44 } 45 46 //AccountOrganization ... 47 type AccountOrganization struct { 48 GUID string `json:"guid"` 49 Region string `json:"region"` 50 } 51 52 type Linkage struct { 53 Origin string `json:"origin"` 54 State string `json:"state"` 55 } 56 57 type BluemixSubscription struct { 58 SoftlayerAccountID string `json:"softlayer_account_id"` 59 } 60 61 //AccountResource ... 62 type AccountResource struct { 63 Resource 64 Entity AccountEntity 65 } 66 67 //AccountEntity ... 68 type AccountEntity struct { 69 Name string `json:"name"` 70 Type string `json:"type"` 71 State string `json:"state"` 72 OwnerGUID string `json:"owner"` 73 OwnerUserID string `json:"owner_userid"` 74 OwnerUniqueID string `json:"owner_unique_id"` 75 CustomerID string `json:"customer_id"` 76 CountryCode string `json:"country_code"` 77 CurrencyCode string `json:"currency_code"` 78 Organizations []AccountOrganization `json:"organizations_region"` 79 Linkages []Linkage `json:"linkages"` 80 BluemixSubscriptions []BluemixSubscription `json:"bluemix_subscriptions"` 81 } 82 83 //AccountServiceAPI is the accountv2 client ... 84 type AccountServiceAPI interface { 85 Accounts() Accounts 86 } 87 88 //MccpService holds the client 89 type accountService struct { 90 *client.Client 91 } 92 93 //New ... 94 func NewAccountServiceAPI(sess *session.Session) (AccountServiceAPI, error) { 95 config := sess.Config.Copy() 96 err := config.ValidateConfigForService(ibmcloud.AccountService) 97 if err != nil { 98 return nil, err 99 } 100 if config.HTTPClient == nil { 101 config.HTTPClient = http.NewHTTPClient(config) 102 } 103 tokenRefreher, err := authentication.NewUAARepository(config, &rest.Client{ 104 DefaultHeader: gohttp.Header{ 105 "User-Agent": []string{http.UserAgent()}, 106 }, 107 HTTPClient: config.HTTPClient, 108 }) 109 if err != nil { 110 return nil, err 111 } 112 if config.UAAAccessToken == "" { 113 err := authentication.PopulateTokens(tokenRefreher, config) 114 if err != nil { 115 return nil, err 116 } 117 } 118 if config.Endpoint == nil { 119 ep, err := config.EndpointLocator.AccountManagementEndpoint() 120 if err != nil { 121 return nil, err 122 } 123 config.Endpoint = &ep 124 } 125 return &accountService{ 126 Client: client.New(config, ibmcloud.AccountService, tokenRefreher), 127 }, nil 128 } 129 130 //Accounts API 131 func (a *accountService) Accounts() Accounts { 132 return newAccountAPI(a.Client) 133 } 134 135 //ToModel ... 136 func (resource AccountResource) ToModel() Account { 137 entity := resource.Entity 138 var imsAccountID string 139 for _, linkage := range entity.Linkages { 140 if (linkage.Origin == "IMS") && (linkage.State == "COMPLETE") { 141 for _, subscription := range entity.BluemixSubscriptions { 142 imsAccountID = subscription.SoftlayerAccountID 143 } 144 } 145 } 146 return Account{ 147 GUID: resource.Metadata.GUID, 148 Name: entity.Name, 149 Type: entity.Type, 150 State: entity.State, 151 OwnerGUID: entity.OwnerGUID, 152 OwnerUserID: entity.OwnerUserID, 153 OwnerUniqueID: entity.OwnerUniqueID, 154 CustomerID: entity.CustomerID, 155 CountryCode: entity.CountryCode, 156 CurrencyCode: entity.CurrencyCode, 157 Organizations: entity.Organizations, 158 IMSAccountID: imsAccountID, 159 } 160 } 161 162 func (nameQueryResponse AccountNameQueryResponse) ToModel() Account { 163 entity := nameQueryResponse.Entity 164 guid := nameQueryResponse.Metadata.GUID 165 166 var imsAccountID string 167 for _, linkage := range entity.Linkages { 168 if (linkage.Origin == "IMS") && (linkage.State == "COMPLETE") { 169 for _, subscription := range entity.BluemixSubscriptions { 170 imsAccountID = subscription.SoftlayerAccountID 171 } 172 } 173 } 174 return Account{ 175 GUID: guid, 176 Name: entity.Name, 177 Type: entity.Type, 178 State: entity.State, 179 OwnerGUID: entity.OwnerGUID, 180 OwnerUserID: entity.OwnerUserID, 181 OwnerUniqueID: entity.OwnerUniqueID, 182 CustomerID: entity.CustomerID, 183 CountryCode: entity.CountryCode, 184 CurrencyCode: entity.CurrencyCode, 185 Organizations: entity.Organizations, 186 IMSAccountID: imsAccountID, 187 } 188 } 189 190 //AccountQueryResponse ... 191 type AccountQueryResponse struct { 192 Metadata Metadata 193 Accounts []AccountResource `json:"resources"` 194 } 195 196 //AccountQueryResponse ... 197 type AccountNameQueryResponse struct { 198 Metadata Metadata 199 Entity AccountEntity 200 } 201 202 //Accounts ... 203 type Accounts interface { 204 List() ([]Account, error) 205 FindByOrg(orgGUID string, region string) (*Account, error) 206 FindByOwner(userID string) (*Account, error) 207 Get(accountId string) (*Account, error) 208 } 209 210 type account struct { 211 client *client.Client 212 } 213 214 func newAccountAPI(c *client.Client) Accounts { 215 return &account{ 216 client: c, 217 } 218 } 219 220 //FindByOrg ... 221 func (a *account) FindByOrg(orgGUID, region string) (*Account, error) { 222 type organizationRegion struct { 223 GUID string `json:"guid"` 224 Region string `json:"region"` 225 } 226 227 payLoad := struct { 228 OrganizationsRegion []organizationRegion `json:"organizations_region"` 229 }{ 230 OrganizationsRegion: []organizationRegion{ 231 { 232 GUID: orgGUID, 233 Region: region, 234 }, 235 }, 236 } 237 238 queryResp := AccountQueryResponse{} 239 response, err := a.client.Post("/coe/v2/getaccounts", payLoad, &queryResp) 240 if err != nil { 241 242 if response.StatusCode == 404 { 243 return nil, bmxerror.New(accountv2.ErrCodeNoAccountExists, 244 fmt.Sprintf("No account exists in the given region: %q and the given org: %q", region, orgGUID)) 245 } 246 return nil, err 247 248 } 249 250 if len(queryResp.Accounts) > 0 { 251 account := queryResp.Accounts[0].ToModel() 252 return &account, nil 253 } 254 255 return nil, bmxerror.New(accountv2.ErrCodeNoAccountExists, 256 fmt.Sprintf("No account exists in the given region: %q and the given org: %q", region, orgGUID)) 257 } 258 259 func (a *account) List() ([]Account, error) { 260 var accounts []Account 261 resp, err := a.client.GetPaginated("/coe/v2/accounts", accountv2.NewAccountPaginatedResources(AccountResource{}), func(resource interface{}) bool { 262 if accountResource, ok := resource.(AccountResource); ok { 263 accounts = append(accounts, accountResource.ToModel()) 264 return true 265 } 266 return false 267 }) 268 269 if resp.StatusCode == 404 || len(accounts) == 0 { 270 return nil, bmxerror.New(accountv2.ErrCodeNoAccountExists, 271 fmt.Sprintf("No Account exists")) 272 } 273 274 return accounts, err 275 } 276 277 //FindByOwner ... 278 func (a *account) FindByOwner(userID string) (*Account, error) { 279 accounts, err := a.List() 280 if err != nil { 281 return nil, err 282 } 283 284 for _, a := range accounts { 285 if a.OwnerUserID == userID { 286 return &a, nil 287 } 288 } 289 return nil, bmxerror.New(accountv2.ErrCodeNoAccountExists, 290 fmt.Sprintf("No account exists for the user %q", userID)) 291 } 292 293 //Get ... 294 func (a *account) Get(accountId string) (*Account, error) { 295 queryResp := AccountNameQueryResponse{} 296 response, err := a.client.Get(fmt.Sprintf("/coe/v2/accounts/%s", accountId), &queryResp) 297 if err != nil { 298 299 if response.StatusCode == 404 { 300 return nil, bmxerror.New(accountv2.ErrCodeNoAccountExists, 301 fmt.Sprintf("Account %q does not exists", accountId)) 302 } 303 return nil, err 304 305 } 306 307 account := queryResp.ToModel() 308 return &account, nil 309 310 }