Skip to content

Commit

Permalink
Support Lifecycle Release Bundle Distribute (#797)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobiNino authored Aug 30, 2023
1 parent 653986a commit df2d2a8
Show file tree
Hide file tree
Showing 16 changed files with 380 additions and 214 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1614,9 +1614,9 @@ summary, err := distManager.SignReleaseBundle(params)
#### Async Distributing a Release Bundle v1

```go
params := services.NewDistributeReleaseBundleParams("bundle-name", "1")
distributionRules := utils.DistributionCommonParams{SiteName: "Swamp-1", "CityName": "Tel-Aviv", "CountryCodes": []string{"123"}}}
params.DistributionRules = []*utils.DistributionCommonParams{distributionRules}
params := distribution.NewDistributeReleaseBundleParams("bundle-name", "1")
distributionRules := distribution.DistributionCommonParams{SiteName: "Swamp-1", "CityName": "Tel-Aviv", "CountryCodes": []string{"123"}}}
params.DistributionRules = []*distribution.DistributionCommonParams{distributionRules}
// Auto-creating repository if it does not exist
autoCreateRepo := true
err := distManager.DistributeReleaseBundle(params, autoCreateRepo)
Expand All @@ -1625,9 +1625,9 @@ err := distManager.DistributeReleaseBundle(params, autoCreateRepo)
#### Sync Distributing a Release Bundle v1

```go
params := services.NewDistributeReleaseBundleParams("bundle-name", "1")
distributionRules := utils.DistributionCommonParams{SiteName: "Swamp-1", "CityName": "Tel-Aviv", "CountryCodes": []string{"123"}}}
params.DistributionRules = []*utils.DistributionCommonParams{distributionRules}
params := distribution.NewDistributeReleaseBundleParams("bundle-name", "1")
distributionRules := distribution.DistributionCommonParams{SiteName: "Swamp-1", "CityName": "Tel-Aviv", "CountryCodes": []string{"123"}}}
params.DistributionRules = []*distribution.DistributionCommonParams{distributionRules}
// Auto-creating repository if it does not exist
autoCreateRepo := true
// Wait up to 120 minutes for the release bundle v1 distribution
Expand All @@ -1654,8 +1654,8 @@ status, err := distributeBundleService.GetStatus(params)
```go
params := services.NewDeleteReleaseBundleParams("bundle-name", "1")
params.DeleteFromDistribution = true
distributionRules := utils.DistributionCommonParams{SiteName: "Swamp-1", "CityName": "Tel-Aviv", "CountryCodes": []string{"123"}}}
params.DistributionRules = []*utils.DistributionCommonParams{distributionRules}
distributionRules := distribution.DistributionCommonParams{SiteName: "Swamp-1", "CityName": "Tel-Aviv", "CountryCodes": []string{"123"}}}
params.DistributionRules = []*distribution.DistributionCommonParams{distributionRules}
// Set to true to enable sync deletion (the command execution will end when the deletion process ends).
param.Sync = true
// Max minutes to wait for sync deletion.
Expand Down
15 changes: 9 additions & 6 deletions distribution/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/jfrog/jfrog-client-go/distribution/services"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/distribution"
)

type DistributionServicesManager struct {
Expand Down Expand Up @@ -57,22 +58,24 @@ func (sm *DistributionServicesManager) SignReleaseBundle(params services.SignBun
return signBundleService.SignReleaseBundle(params)
}

func (sm *DistributionServicesManager) DistributeReleaseBundle(params services.DistributionParams, autoCreateRepo bool) error {
distributeBundleService := services.NewDistributeReleaseBundleService(sm.client)
func (sm *DistributionServicesManager) DistributeReleaseBundle(params distribution.DistributionParams, autoCreateRepo bool) error {
distributeBundleService := services.NewDistributeReleaseBundleV1Service(sm.client)
distributeBundleService.DistDetails = sm.config.GetServiceDetails()
distributeBundleService.DryRun = sm.config.IsDryRun()
distributeBundleService.AutoCreateRepo = autoCreateRepo
return distributeBundleService.Distribute(params)
distributeBundleService.DistributeParams = params
return distributeBundleService.Distribute()
}

func (sm *DistributionServicesManager) DistributeReleaseBundleSync(params services.DistributionParams, maxWaitMinutes int, autoCreateRepo bool) error {
distributeBundleService := services.NewDistributeReleaseBundleService(sm.client)
func (sm *DistributionServicesManager) DistributeReleaseBundleSync(params distribution.DistributionParams, maxWaitMinutes int, autoCreateRepo bool) error {
distributeBundleService := services.NewDistributeReleaseBundleV1Service(sm.client)
distributeBundleService.DistDetails = sm.config.GetServiceDetails()
distributeBundleService.DryRun = sm.config.IsDryRun()
distributeBundleService.MaxWaitMinutes = maxWaitMinutes
distributeBundleService.Sync = true
distributeBundleService.AutoCreateRepo = autoCreateRepo
return distributeBundleService.Distribute(params)
distributeBundleService.DistributeParams = params
return distributeBundleService.Distribute()
}

func (sm *DistributionServicesManager) GetDistributionStatus(params services.DistributionStatusParams) (*[]services.DistributionStatusResponse, error) {
Expand Down
13 changes: 7 additions & 6 deletions distribution/services/deleteremote.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/distribution"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"net/http"
Expand Down Expand Up @@ -43,9 +44,9 @@ func (dr *DeleteReleaseBundleService) IsDryRun() bool {
}

func (dr *DeleteReleaseBundleService) DeleteDistribution(deleteDistributionParams DeleteDistributionParams) error {
var distributionRules []DistributionRulesBody
var distributionRules []distribution.DistributionRulesBody
for _, rule := range deleteDistributionParams.DistributionRules {
distributionRule := DistributionRulesBody{
distributionRule := distribution.DistributionRulesBody{
SiteName: rule.GetSiteName(),
CityName: rule.GetCityName(),
CountryCodes: rule.GetCountryCodes(),
Expand All @@ -61,7 +62,7 @@ func (dr *DeleteReleaseBundleService) DeleteDistribution(deleteDistributionParam
}

deleteDistribution := DeleteRemoteDistributionBody{
DistributionBody: DistributionBody{
ReleaseBundleDistributeV1Body: distribution.ReleaseBundleDistributeV1Body{
DryRun: dr.DryRun,
DistributionRules: distributionRules,
},
Expand Down Expand Up @@ -133,12 +134,12 @@ func (dr *DeleteReleaseBundleService) waitForDeletion(name, version string) erro
}

type DeleteRemoteDistributionBody struct {
DistributionBody
distribution.ReleaseBundleDistributeV1Body
OnSuccess OnSuccess `json:"on_success"`
}

type DeleteDistributionParams struct {
DistributionParams
distribution.DistributionParams
DeleteFromDistribution bool
Sync bool
// Max time in minutes to wait for sync distribution to finish.
Expand All @@ -147,7 +148,7 @@ type DeleteDistributionParams struct {

func NewDeleteReleaseBundleParams(name, version string) DeleteDistributionParams {
return DeleteDistributionParams{
DistributionParams: DistributionParams{
DistributionParams: distribution.DistributionParams{
Name: name,
Version: version,
},
Expand Down
138 changes: 44 additions & 94 deletions distribution/services/distribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,109 +3,88 @@ package services
import (
"encoding/json"
"fmt"
"net/http"

artifactoryUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
"github.com/jfrog/jfrog-client-go/auth"
distributionUtils "github.com/jfrog/jfrog-client-go/distribution/services/utils"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/utils"
clientUtils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/distribution"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/log"
)

const defaultMaxWaitMinutes = 60 // 1 hour
const DefaultDistributeSyncSleepIntervalSeconds = 10 // 10 seconds

type DistributeReleaseBundleService struct {
type DistributeReleaseBundleV1Service struct {
client *jfroghttpclient.JfrogHttpClient
DistDetails auth.ServiceDetails
DryRun bool
Sync bool
AutoCreateRepo bool
// Max time in minutes to wait for sync distribution to finish.
MaxWaitMinutes int
MaxWaitMinutes int
DistributeParams distribution.DistributionParams
}

func NewDistributeReleaseBundleService(client *jfroghttpclient.JfrogHttpClient) *DistributeReleaseBundleService {
return &DistributeReleaseBundleService{client: client}
func (dr *DistributeReleaseBundleV1Service) GetHttpClient() *jfroghttpclient.JfrogHttpClient {
return dr.client
}

func (dr *DistributeReleaseBundleService) GetDistDetails() auth.ServiceDetails {
func (dr *DistributeReleaseBundleV1Service) ServiceDetails() auth.ServiceDetails {
return dr.DistDetails
}

func (dr *DistributeReleaseBundleService) Distribute(distributeParams DistributionParams) error {
var distributionRules []DistributionRulesBody
for _, spec := range distributeParams.DistributionRules {
distributionRule := DistributionRulesBody{
SiteName: spec.GetSiteName(),
CityName: spec.GetCityName(),
CountryCodes: spec.GetCountryCodes(),
}
distributionRules = append(distributionRules, distributionRule)
}
distribution := &DistributionBody{
DryRun: dr.DryRun,
DistributionRules: distributionRules,
AutoCreateRepo: dr.AutoCreateRepo,
}
func (dr *DistributeReleaseBundleV1Service) IsDryRun() bool {
return dr.DryRun
}

trackerId, err := dr.execDistribute(distributeParams.Name, distributeParams.Version, distribution)
if err != nil || !dr.Sync || dr.DryRun {
return err
}
func (dr *DistributeReleaseBundleV1Service) IsSync() bool {
return dr.Sync
}

// Sync distribution
return dr.waitForDistribution(&distributeParams, trackerId)
func (dr *DistributeReleaseBundleV1Service) GetMaxWaitMinutes() int {
return dr.MaxWaitMinutes
}

func (dr *DistributeReleaseBundleService) execDistribute(name, version string, distribution *DistributionBody) (json.Number, error) {
httpClientsDetails := dr.DistDetails.CreateHttpClientDetails()
content, err := json.Marshal(distribution)
if err != nil {
return "", errorutils.CheckError(err)
}
dryRunStr := ""
if distribution.DryRun {
dryRunStr = "[Dry run] "
}
log.Info(dryRunStr + "Distributing: " + name + "/" + version)
func (dr *DistributeReleaseBundleV1Service) GetRestApi(name, version string) string {
return "api/v1/distribution/" + name + "/" + version
}

url := dr.DistDetails.GetUrl() + "api/v1/distribution/" + name + "/" + version
artifactoryUtils.SetContentType("application/json", &httpClientsDetails.Headers)
resp, body, err := dr.client.SendPost(url, content, &httpClientsDetails)
if err != nil {
return "", err
}
if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK, http.StatusAccepted); err != nil {
return "", err
}
response := DistributionResponseBody{}
err = json.Unmarshal(body, &response)
if err != nil {
return "", errorutils.CheckError(err)
func (dr *DistributeReleaseBundleV1Service) GetDistributeBody() any {
return distribution.CreateDistributeV1Body(dr.DistributeParams, dr.DryRun, dr.AutoCreateRepo)
}

func (dr *DistributeReleaseBundleV1Service) GetDistributionParams() distribution.DistributionParams {
return dr.DistributeParams
}

func NewDistributeReleaseBundleV1Service(client *jfroghttpclient.JfrogHttpClient) *DistributeReleaseBundleV1Service {
return &DistributeReleaseBundleV1Service{client: client}
}

func (dr *DistributeReleaseBundleV1Service) Distribute() error {
trackerId, err := distribution.DoDistribute(dr)
if err != nil || !dr.IsSync() || dr.IsDryRun() {
return err
}

log.Debug("Distribution response:", resp.Status)
log.Debug(utils.IndentJson(body))
return response.TrackerId, nil
// Sync distribution
return dr.waitForDistribution(&dr.DistributeParams, trackerId)
}

func (dr *DistributeReleaseBundleService) waitForDistribution(distributeParams *DistributionParams, trackerId json.Number) error {
distributeBundleService := NewDistributionStatusService(dr.client)
distributeBundleService.DistDetails = dr.GetDistDetails()
func (dr *DistributeReleaseBundleV1Service) waitForDistribution(distributeParams *distribution.DistributionParams, trackerId json.Number) error {
distributeBundleService := NewDistributionStatusService(dr.GetHttpClient())
distributeBundleService.DistDetails = dr.ServiceDetails()
distributionStatusParams := DistributionStatusParams{
Name: distributeParams.Name,
Version: distributeParams.Version,
TrackerId: trackerId.String(),
}
maxWaitMinutes := defaultMaxWaitMinutes
if dr.MaxWaitMinutes >= 1 {
maxWaitMinutes = dr.MaxWaitMinutes
if dr.GetMaxWaitMinutes() >= 1 {
maxWaitMinutes = dr.GetMaxWaitMinutes()
}
distributingMessage := fmt.Sprintf("Sync: Distributing %s/%s...", distributeParams.Name, distributeParams.Version)
retryExecutor := &utils.RetryExecutor{
retryExecutor := &clientUtils.RetryExecutor{
MaxRetries: maxWaitMinutes * 60 / DefaultDistributeSyncSleepIntervalSeconds,
RetriesIntervalMilliSecs: DefaultDistributeSyncSleepIntervalSeconds * 1000,
ErrorMessage: "",
Expand All @@ -120,7 +99,7 @@ func (dr *DistributeReleaseBundleService) waitForDistribution(distributeParams *
if err != nil {
return false, errorutils.CheckError(err)
}
return false, errorutils.CheckErrorf("Distribution failed: " + utils.IndentJson(bytes))
return false, errorutils.CheckErrorf("Distribution failed: " + clientUtils.IndentJson(bytes))
}
if (*response)[0].Status == Completed {
log.Info("Distribution Completed!")
Expand All @@ -133,32 +112,3 @@ func (dr *DistributeReleaseBundleService) waitForDistribution(distributeParams *
}
return retryExecutor.Execute()
}

type DistributionBody struct {
DryRun bool `json:"dry_run"`
DistributionRules []DistributionRulesBody `json:"distribution_rules"`
AutoCreateRepo bool `json:"auto_create_missing_repositories,omitempty"`
}

type DistributionRulesBody struct {
SiteName string `json:"site_name,omitempty"`
CityName string `json:"city_name,omitempty"`
CountryCodes []string `json:"country_codes,omitempty"`
}

type DistributionResponseBody struct {
TrackerId json.Number `json:"id"`
}

type DistributionParams struct {
DistributionRules []*distributionUtils.DistributionCommonParams
Name string
Version string
}

func NewDistributeReleaseBundleParams(name, version string) DistributionParams {
return DistributionParams{
Name: name,
Version: version,
}
}
17 changes: 9 additions & 8 deletions distribution/services/getstatus.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package services
import (
"encoding/json"
"errors"
"github.com/jfrog/jfrog-client-go/utils/distribution"
"net/http"
"strings"

Expand Down Expand Up @@ -109,14 +110,14 @@ const (
)

type DistributionStatusResponse struct {
Id json.Number `json:"distribution_id"`
FriendlyId json.Number `json:"distribution_friendly_id,omitempty"`
Type DistributionType `json:"type,omitempty"`
Name string `json:"release_bundle_name,omitempty"`
Version string `json:"release_bundle_version,omitempty"`
Status DistributionStatus `json:"status,omitempty"`
DistributionRules []DistributionRulesBody `json:"distribution_rules,omitempty"`
Sites []DistributionSiteStatus `json:"sites,omitempty"`
Id json.Number `json:"distribution_id"`
FriendlyId json.Number `json:"distribution_friendly_id,omitempty"`
Type DistributionType `json:"type,omitempty"`
Name string `json:"release_bundle_name,omitempty"`
Version string `json:"release_bundle_version,omitempty"`
Status DistributionStatus `json:"status,omitempty"`
DistributionRules []distribution.DistributionRulesBody `json:"distribution_rules,omitempty"`
Sites []DistributionSiteStatus `json:"sites,omitempty"`
}

type DistributionSiteStatus struct {
Expand Down
Loading

0 comments on commit df2d2a8

Please sign in to comment.