github.com/jfrog/jfrog-client-go@v1.40.2/pipelines/services/integration.go (about) 1 package services 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "strconv" 7 "strings" 8 9 "github.com/jfrog/jfrog-client-go/auth" 10 "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" 11 "github.com/jfrog/jfrog-client-go/utils" 12 "github.com/jfrog/jfrog-client-go/utils/errorutils" 13 "github.com/jfrog/jfrog-client-go/utils/log" 14 ) 15 16 type IntegrationsService struct { 17 client *jfroghttpclient.JfrogHttpClient 18 auth.ServiceDetails 19 } 20 21 func NewIntegrationsService(client *jfroghttpclient.JfrogHttpClient) *IntegrationsService { 22 return &IntegrationsService{client: client} 23 } 24 25 const ( 26 ArtifactoryName = "artifactory" 27 artifactoryId = 98 28 GithubName = "github" 29 githubId = 20 30 GithubEnterpriseName = "githubEnterprise" 31 githubEnterpriseId = 15 32 githubDefaultUrl = "https://api.github.com" 33 BitbucketName = "bitbucket" 34 bitbucketId = 16 35 bitbucketDefaultUrl = "https://api.bitbucket.org" 36 BitbucketServerName = "bitbucketServerBasic" 37 bitbucketServerId = 90 38 GitlabName = "gitlab" 39 gitlabId = 21 40 41 defaultProjectId = 1 42 43 urlLabel = "url" 44 tokenLabel = "token" 45 userLabel = "user" 46 usernameLabel = "username" 47 apikeyLabel = "apikey" 48 passwordLabel = "password" 49 50 integrationsRestApi = "api/v1/projectIntegrations/" 51 ) 52 53 func (is *IntegrationsService) CreateGithubIntegration(integrationName, token string) (id int, err error) { 54 integration := IntegrationCreation{ 55 Integration: Integration{ 56 Name: integrationName, 57 MasterIntegrationId: githubId, 58 MasterIntegrationName: GithubName, 59 ProjectId: defaultProjectId, 60 }, 61 FormJSONValues: []jsonValues{ 62 {urlLabel, githubDefaultUrl}, 63 {tokenLabel, token}, 64 }, 65 } 66 return is.createIntegration(integration) 67 } 68 69 func (is *IntegrationsService) CreateGithubEnterpriseIntegration(integrationName, url, token string) (id int, err error) { 70 integration := IntegrationCreation{ 71 Integration: Integration{ 72 Name: integrationName, 73 MasterIntegrationId: githubEnterpriseId, 74 MasterIntegrationName: GithubEnterpriseName, 75 ProjectId: defaultProjectId, 76 }, 77 FormJSONValues: []jsonValues{ 78 {urlLabel, url}, 79 {tokenLabel, token}, 80 }, 81 } 82 return is.createIntegration(integration) 83 } 84 85 func (is *IntegrationsService) CreateBitbucketIntegration(integrationName, username, token string) (id int, err error) { 86 integration := IntegrationCreation{ 87 Integration: Integration{ 88 Name: integrationName, 89 MasterIntegrationId: bitbucketId, 90 MasterIntegrationName: BitbucketName, 91 ProjectId: defaultProjectId}, 92 FormJSONValues: []jsonValues{ 93 {urlLabel, bitbucketDefaultUrl}, 94 {usernameLabel, username}, 95 {tokenLabel, token}, 96 }, 97 } 98 return is.createIntegration(integration) 99 } 100 101 func (is *IntegrationsService) CreateBitbucketServerIntegration(integrationName, url, username, passwordOrToken string) (id int, err error) { 102 integration := IntegrationCreation{ 103 Integration: Integration{ 104 Name: integrationName, 105 MasterIntegrationId: bitbucketServerId, 106 MasterIntegrationName: BitbucketServerName, 107 ProjectId: defaultProjectId}, 108 FormJSONValues: []jsonValues{ 109 {urlLabel, url}, 110 {usernameLabel, username}, 111 {passwordLabel, passwordOrToken}, 112 }, 113 } 114 return is.createIntegration(integration) 115 } 116 117 func (is *IntegrationsService) CreateGitlabIntegration(integrationName, url, token string) (id int, err error) { 118 integration := IntegrationCreation{ 119 Integration: Integration{ 120 Name: integrationName, 121 MasterIntegrationId: gitlabId, 122 MasterIntegrationName: GitlabName, 123 ProjectId: defaultProjectId}, 124 FormJSONValues: []jsonValues{ 125 {urlLabel, url}, 126 {tokenLabel, token}, 127 }, 128 } 129 return is.createIntegration(integration) 130 } 131 132 func (is *IntegrationsService) CreateArtifactoryIntegration(integrationName, url, user, apikey string) (id int, err error) { 133 integration := IntegrationCreation{ 134 Integration: Integration{ 135 Name: integrationName, 136 MasterIntegrationId: artifactoryId, 137 MasterIntegrationName: ArtifactoryName, 138 ProjectId: defaultProjectId}, 139 FormJSONValues: []jsonValues{ 140 {urlLabel, strings.TrimSuffix(url, "/")}, 141 {userLabel, user}, 142 {apikeyLabel, apikey}, 143 }, 144 } 145 return is.createIntegration(integration) 146 } 147 148 func (is *IntegrationsService) createIntegration(integration IntegrationCreation) (id int, err error) { 149 log.Debug("Creating " + integration.MasterIntegrationName + " integration...") 150 content, err := json.Marshal(integration) 151 if err != nil { 152 return -1, errorutils.CheckError(err) 153 } 154 httpDetails := is.ServiceDetails.CreateHttpClientDetails() 155 headers := map[string]string{ 156 "Content-Type": "application/json", 157 "Accept": "application/json", 158 } 159 utils.MergeMaps(httpDetails.Headers, headers) 160 httpDetails.Headers = headers 161 162 resp, body, err := is.client.SendPost(is.ServiceDetails.GetUrl()+integrationsRestApi, content, &httpDetails) 163 if err != nil { 164 return -1, err 165 } 166 if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK, http.StatusCreated); err != nil { 167 if resp.StatusCode == http.StatusConflict { 168 return -1, &IntegrationAlreadyExistsError{InnerError: err} 169 } 170 if resp.StatusCode == http.StatusUnauthorized { 171 return -1, &IntegrationUnauthorizedError{InnerError: err} 172 } 173 return -1, err 174 } 175 176 created := &Integration{} 177 err = json.Unmarshal(body, created) 178 return created.Id, errorutils.CheckError(err) 179 } 180 181 type Integration struct { 182 Name string `json:"name,omitempty"` 183 MasterIntegrationId int `json:"masterIntegrationId,omitempty"` 184 MasterIntegrationName string `json:"masterIntegrationName,omitempty"` 185 ProjectId int `json:"projectId,omitempty"` 186 Environments []string `json:"environments,omitempty"` 187 // Following fields returned when fetching or creating integration: 188 Id int `json:"id,omitempty"` 189 } 190 191 // Using this separate struct for creation because FormJSONValues may have values of any type. 192 type IntegrationCreation struct { 193 Integration 194 FormJSONValues []jsonValues `json:"formJSONValues,omitempty"` 195 } 196 197 type jsonValues struct { 198 Label string `json:"label,omitempty"` 199 Value string `json:"value,omitempty"` 200 } 201 202 func (is *IntegrationsService) DeleteIntegration(integrationId int) error { 203 log.Debug("Deleting integration by id '" + strconv.Itoa(integrationId) + "'...") 204 httpDetails := is.ServiceDetails.CreateHttpClientDetails() 205 resp, body, err := is.client.SendDelete(is.ServiceDetails.GetUrl()+integrationsRestApi+strconv.Itoa(integrationId), nil, &httpDetails) 206 if err != nil { 207 return err 208 } 209 return errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK) 210 } 211 212 func (is *IntegrationsService) GetIntegrationById(integrationId int) (*Integration, error) { 213 log.Debug("Getting integration by id '" + strconv.Itoa(integrationId) + "'...") 214 httpDetails := is.ServiceDetails.CreateHttpClientDetails() 215 url := is.ServiceDetails.GetUrl() + integrationsRestApi + strconv.Itoa(integrationId) 216 resp, body, _, err := is.client.SendGet(url, true, &httpDetails) 217 if err != nil { 218 return nil, err 219 } 220 if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK); err != nil { 221 return nil, err 222 } 223 integration := &Integration{} 224 err = json.Unmarshal(body, integration) 225 return integration, errorutils.CheckError(err) 226 } 227 228 func (is *IntegrationsService) GetIntegrationByName(name string) (*Integration, error) { 229 log.Debug("Getting integration by name '" + name + "'...") 230 integrations, err := is.GetAllIntegrations() 231 if err != nil { 232 return nil, err 233 } 234 for _, integration := range integrations { 235 if integration.Name == name { 236 return &integration, nil 237 } 238 } 239 return nil, errorutils.CheckErrorf("integration with provided name was not found in pipelines") 240 } 241 242 func (is *IntegrationsService) GetAllIntegrations() ([]Integration, error) { 243 rawIntegrations, err := is.GetAllRawIntegrations() 244 if err != nil { 245 return nil, err 246 } 247 integrations := &[]Integration{} 248 err = json.Unmarshal(rawIntegrations, integrations) 249 return *integrations, errorutils.CheckError(err) 250 } 251 252 // GetAllRawIntegrations returns the response returned from integrations api without unmarshalling 253 // into Integration struct. 254 func (is *IntegrationsService) GetAllRawIntegrations() ([]byte, error) { 255 log.Debug("Fetching all integrations...") 256 httpDetails := is.ServiceDetails.CreateHttpClientDetails() 257 url := is.ServiceDetails.GetUrl() + integrationsRestApi 258 resp, body, _, err := is.client.SendGet(url, true, &httpDetails) 259 if err != nil { 260 return nil, err 261 } 262 if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK); err != nil { 263 return nil, err 264 } 265 return body, errorutils.CheckError(err) 266 } 267 268 type IntegrationAlreadyExistsError struct { 269 InnerError error 270 } 271 272 func (*IntegrationAlreadyExistsError) Error() string { 273 return "Pipelines: Integration already exists." 274 } 275 276 type IntegrationUnauthorizedError struct { 277 InnerError error 278 } 279 280 func (*IntegrationUnauthorizedError) Error() string { 281 return "Pipelines: Integration failed, received 401 Unauthorized." 282 }