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  }