├── .gitignore ├── CONTRIBUTING.adoc ├── Dockerfile ├── LICENSE ├── NOTICE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── acceptance ├── acceptance_suite_test.go ├── check_test.go ├── helpers.go ├── in_test.go ├── lifecycle_test.go └── out_test.go ├── bin └── test ├── check ├── check_command.go ├── check_command_test.go ├── check_suite_test.go ├── checkfakes │ ├── fake_filter.go │ ├── fake_pivnet_client.go │ └── fake_sorter.go └── package.go ├── cmd ├── check │ └── main.go ├── in │ └── main.go └── out │ └── main.go ├── concourse ├── sanitized_input.go └── types.go ├── downloader ├── downloader.go ├── downloader_suite_test.go ├── downloader_test.go ├── downloaderfakes │ ├── fake_client.go │ └── fake_extended_client.go └── package.go ├── examples ├── README.md ├── get-aws-vsphere-stemcells.yml └── put-p-mysql.yml ├── filter ├── filter.go ├── filter_suite_test.go └── filter_test.go ├── globs ├── globs.go ├── globs_suite_test.go └── globs_test.go ├── go.mod ├── go.sum ├── gp └── gp.go ├── in ├── archive.go ├── filesystem │ ├── filesystem_command_test.go │ ├── filesystem_suite_test.go │ └── filewriter.go ├── in_command.go ├── in_command_test.go ├── in_suite_test.go ├── infakes │ ├── fake_archive.go │ ├── fake_downloader.go │ ├── fake_file_summer.go │ ├── fake_file_writer.go │ ├── fake_filter.go │ └── fake_pivnet_client.go └── package.go ├── metadata ├── README.md ├── metadata.go ├── metadata_suite_test.go └── metadata_test.go ├── out ├── out_command.go ├── out_command_test.go ├── out_suite_test.go ├── outfakes │ ├── creator.go │ ├── dependency_specifiers_creator.go │ ├── finalizer.go │ ├── finder.go │ ├── globber.go │ ├── release_artifact_references_adder.go │ ├── release_dependencies_adder.go │ ├── release_file_groups_adder.go │ ├── release_upgrade_paths_adder.go │ ├── upgrade_path_specifiers_creator.go │ ├── uploader.go │ ├── user_groups_updater.go │ └── validation.go ├── package.go └── release │ ├── dependency_specifiers.go │ ├── dependency_specifiers_test.go │ ├── init_test.go │ ├── package.go │ ├── release_artifact_references.go │ ├── release_artifact_references_test.go │ ├── release_creator.go │ ├── release_creator_test.go │ ├── release_dependencies.go │ ├── release_dependencies_test.go │ ├── release_file_groups.go │ ├── release_file_groups_test.go │ ├── release_finalizer.go │ ├── release_finalizer_test.go │ ├── release_finder.go │ ├── release_finder_test.go │ ├── release_uploader.go │ ├── release_uploader_test.go │ ├── releasefakes │ ├── dependency_specifiers_creator_client.go │ ├── fake_filter.go │ ├── fake_semver_converter.go │ ├── finalizer_client.go │ ├── finder_client.go │ ├── md5summer.go │ ├── release_artifact_references_adder_client.go │ ├── release_client.go │ ├── release_dependencies_adder_client.go │ ├── release_file_groups_adder_client.go │ ├── release_upgrade_paths_adder_client.go │ ├── s3client.go │ ├── sha256summer.go │ ├── update_client.go │ ├── upgrade_path_specifiers_creator_client.go │ ├── upload_client.go │ └── user_groups_updater_client.go │ ├── upgrade_path_specifiers.go │ ├── upgrade_path_specifiers_test.go │ ├── upgrade_paths.go │ ├── upgrade_paths_test.go │ ├── user_groups.go │ └── user_groups_test.go ├── s3 ├── package.go ├── s3_client.go ├── s3_client_test.go ├── s3_suite_test.go └── s3fakes │ └── fake_file_size_getter.go ├── scripts └── build ├── semver ├── semver.go ├── semver_suite_test.go └── semver_test.go ├── sorter ├── package.go ├── sorter.go ├── sorter_suite_test.go ├── sorter_test.go └── sorterfakes │ └── fake_semver_converter.go ├── tools └── tools.go ├── ui └── ui.go ├── uploader ├── package.go ├── prefix_finder.go ├── prefix_finder_test.go ├── uploader.go ├── uploader_suite_test.go ├── uploader_test.go └── uploaderfakes │ ├── fake_s3prefix_fetcher.go │ └── fake_transport.go ├── useragent ├── useragent.go ├── useragent_suite_test.go └── useragent_test.go ├── validator ├── check_validator.go ├── check_validator_test.go ├── in_validator.go ├── in_validator_test.go ├── out_validator.go ├── out_validator_test.go └── validator_suite_test.go └── versions ├── versions.go ├── versions_suite_test.go └── versions_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | /cmd/check/check 2 | /cmd/in/in 3 | /cmd/out/out 4 | 5 | s3-out 6 | /cmd/out/s3-out 7 | 8 | main 9 | vendor 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.adoc: -------------------------------------------------------------------------------- 1 | If you have not previously done so, please fill out and 2 | submit the https://cla.pivotal.io/sign/pivotal[Contributor License Agreement]. 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:jammy 2 | 3 | RUN apt-get update && apt-get install -y unzip ca-certificates && rm -rf /var/lib/apt/lists/* 4 | 5 | COPY cmd/check/check /opt/resource/check 6 | COPY cmd/in/in /opt/resource/in 7 | COPY cmd/out/out /opt/resource/out 8 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Pivotal Network (concourse-) Resource 2 | 3 | Copyright (c) 2015-2016 Pivotal, Inc. All Rights Reserved. 4 | 5 | This product is licensed to you under the Apache License, Version 2.0 (the "License"). 6 | You may not use this product except in compliance with the License. 7 | 8 | This product may include a number of subcomponents with separate copyright notices 9 | and license terms. Your use of these subcomponents is subject to the terms and 10 | conditions of the subcomponent's license, as noted in the LICENSE file. 11 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for contributing to the Pivnet Resource! 2 | 3 | - Have you made this pull request to the `develop` branch? 4 | - Have you [run the tests locally](https://github.com/pivotal-cf/pivnet-resource#running-the-tests)? 5 | -------------------------------------------------------------------------------- /acceptance/check_test.go: -------------------------------------------------------------------------------- 1 | package acceptance 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/onsi/gomega/gbytes" 6 | "os/exec" 7 | 8 | . "github.com/onsi/ginkgo" 9 | . "github.com/onsi/gomega" 10 | "github.com/onsi/gomega/gexec" 11 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 12 | ) 13 | 14 | var _ = Describe("Check", func() { 15 | var ( 16 | productSlug = "pivnet-resource-test" 17 | oldestReleaseVersion = "0.0.1-piv-res-test-fixture#2017-06-30T15:41:17.119Z" 18 | 19 | command *exec.Cmd 20 | checkRequest concourse.CheckRequest 21 | stdinContents []byte 22 | ) 23 | 24 | Context("when user provides a UAA refresh token", func() { 25 | BeforeEach(func() { 26 | By("Creating command object") 27 | command = exec.Command(checkPath) 28 | 29 | By("Creating default request") 30 | checkRequest = concourse.CheckRequest{ 31 | Source: concourse.Source{ 32 | APIToken: refreshToken, 33 | ProductSlug: productSlug, 34 | Endpoint: endpoint, 35 | }, 36 | Version: concourse.Version{ 37 | ProductVersion: oldestReleaseVersion, 38 | }, 39 | } 40 | 41 | var err error 42 | stdinContents, err = json.Marshal(checkRequest) 43 | Expect(err).ShouldNot(HaveOccurred()) 44 | }) 45 | 46 | It("fetches a UAA token and uses that token to make the check request", func() { 47 | session := run(command, stdinContents) 48 | Eventually(session, executableTimeout).Should(gexec.Exit(0)) 49 | 50 | By("Outputting a valid json response") 51 | response := concourse.CheckResponse{} 52 | err := json.Unmarshal(session.Out.Contents(), &response) 53 | Expect(err).ShouldNot(HaveOccurred()) 54 | 55 | By("Validating all the expected elements were returned") 56 | Expect(len(response)).Should(BeNumerically(">=", 3)) 57 | 58 | By("Validating the returned elements have the expected product release versions") 59 | Expect(response[0].ProductVersion).To(ContainSubstring("0.0.1-piv-res-test-fixture")) 60 | Expect(response[1].ProductVersion).To(ContainSubstring("1.2.3")) 61 | Expect(response[2].ProductVersion).To(ContainSubstring("2.3.4")) 62 | }) 63 | 64 | Context("when validation fails", func() { 65 | BeforeEach(func() { 66 | checkRequest.Source.ProductSlug = "" 67 | 68 | var err error 69 | stdinContents, err = json.Marshal(checkRequest) 70 | Expect(err).ShouldNot(HaveOccurred()) 71 | }) 72 | 73 | It("exits with error", func() { 74 | By("Running the command") 75 | session := run(command, stdinContents) 76 | 77 | By("Validating command exited with error") 78 | Eventually(session, executableTimeout).Should(gexec.Exit(1)) 79 | Expect(session.Err).Should(gbytes.Say("product_slug must be provided")) 80 | }) 81 | }) 82 | }) 83 | }) 84 | -------------------------------------------------------------------------------- /acceptance/helpers.go: -------------------------------------------------------------------------------- 1 | package acceptance 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os/exec" 7 | "strings" 8 | 9 | "github.com/onsi/gomega/gexec" 10 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 11 | 12 | . "github.com/onsi/ginkgo" 13 | . "github.com/onsi/gomega" 14 | ) 15 | 16 | func run(command *exec.Cmd, stdinContents []byte) *gexec.Session { 17 | fmt.Fprintf(GinkgoWriter, "input: %s\n", stdinContents) 18 | 19 | stdin, err := command.StdinPipe() 20 | Expect(err).ShouldNot(HaveOccurred()) 21 | 22 | session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 23 | Expect(err).NotTo(HaveOccurred()) 24 | 25 | _, err = io.WriteString(stdin, string(stdinContents)) 26 | Expect(err).ShouldNot(HaveOccurred()) 27 | 28 | err = stdin.Close() 29 | Expect(err).ShouldNot(HaveOccurred()) 30 | 31 | return session 32 | } 33 | 34 | func metadataValueForKey(metadata []concourse.Metadata, name string) (string, error) { 35 | for _, i := range metadata { 36 | if i.Name == name { 37 | return i.Value, nil 38 | } 39 | } 40 | return "", fmt.Errorf("name not found: %s", name) 41 | } 42 | 43 | func stringInSlice(a string, list []string) bool { 44 | for _, b := range list { 45 | if b == a { 46 | return true 47 | } 48 | } 49 | return false 50 | } 51 | 52 | func versionsWithoutFingerprints(versionsWithFingerprints []string) []string { 53 | versionsWithoutFingerprints := make([]string, len(versionsWithFingerprints)) 54 | for i, v := range versionsWithFingerprints { 55 | split := strings.Split(v, "#") 56 | versionsWithoutFingerprints[i] = split[0] 57 | } 58 | return versionsWithoutFingerprints 59 | } 60 | -------------------------------------------------------------------------------- /bin/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | PRODUCT_SLUG="${PRODUCT_SLUG:?"PRODUCT_SLUG must be provided"}" 6 | ARTIFACT_NAME="${ARTIFACT_NAME:?"ARTIFACT_NAME must be provided"}" 7 | ARTIFACT_PATH="${ARTIFACT_PATH:?"ARTIFACT_PATH must be provided"}" 8 | ARTIFACT_DIGEST="${ARTIFACT_DIGEST:?"ARTIFACT_DIGEST must be provided"}" 9 | PIVNET_ENDPOINT="${PIVNET_ENDPOINT:?"PIVNET_ENDPOINT must be provided"}" 10 | PIVNET_RESOURCE_REFRESH_TOKEN="${PIVNET_RESOURCE_REFRESH_TOKEN:?"PIVNET_RESOURCE_REFRESH_TOKEN must be provided"}" 11 | 12 | # In seconds 13 | SLOW_SPEC_THRESHOLD="${SLOW_SPEC_THRESHOLD:-60}" 14 | 15 | my_dir="$( cd "$( dirname "${0}" )" && pwd )" 16 | base_dir="$( cd "${my_dir}/.." && pwd )" 17 | 18 | pushd "${base_dir}" > /dev/null 19 | GO111MODULE=on \ 20 | CGO_ENABLED=1 ginkgo \ 21 | -r \ 22 | -race \ 23 | -p \ 24 | -randomizeAllSpecs \ 25 | -randomizeSuites \ 26 | -keepGoing \ 27 | -slowSpecThreshold="${SLOW_SPEC_THRESHOLD}" \ 28 | "$@" 29 | popd > /dev/null 30 | -------------------------------------------------------------------------------- /check/check_suite_test.go: -------------------------------------------------------------------------------- 1 | package check_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | const ( 11 | productSlug = "some-product-name" 12 | ) 13 | 14 | func TestCheck(t *testing.T) { 15 | RegisterFailHandler(Fail) 16 | RunSpecs(t, "Check Suite") 17 | } 18 | -------------------------------------------------------------------------------- /check/package.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /cmd/check/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/pivotal-cf/go-pivnet/v7" 6 | "github.com/pivotal-cf/go-pivnet/v7/logger" 7 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 8 | "github.com/pivotal-cf/pivnet-resource/v3/check" 9 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 10 | "github.com/pivotal-cf/pivnet-resource/v3/filter" 11 | "github.com/pivotal-cf/pivnet-resource/v3/gp" 12 | "github.com/pivotal-cf/pivnet-resource/v3/semver" 13 | "github.com/pivotal-cf/pivnet-resource/v3/sorter" 14 | "github.com/pivotal-cf/pivnet-resource/v3/useragent" 15 | "github.com/pivotal-cf/pivnet-resource/v3/validator" 16 | "github.com/robdimsdale/sanitizer" 17 | "io/ioutil" 18 | "log" 19 | "os" 20 | ) 21 | 22 | var ( 23 | // version is deliberately left uninitialized so it can be set at compile-time 24 | version string 25 | ) 26 | 27 | type AuthResp struct { 28 | Token string `json: "token"` 29 | } 30 | 31 | func main() { 32 | if version == "" { 33 | version = "dev" 34 | } 35 | 36 | var input concourse.CheckRequest 37 | 38 | logFile, err := ioutil.TempFile("", "pivnet-check.log") 39 | if err != nil { 40 | log.Printf("could not create log file") 41 | } 42 | 43 | logger := log.New(logFile, "", log.LstdFlags) 44 | 45 | logger.Printf("PivNet Resource version: %s", version) 46 | 47 | err = json.NewDecoder(os.Stdin).Decode(&input) 48 | if err != nil { 49 | log.Fatalf("Exiting with error: %s", err) 50 | } 51 | 52 | sanitized := concourse.SanitizedSource(input.Source) 53 | logger.SetOutput(sanitizer.NewSanitizer(sanitized, logFile)) 54 | 55 | verbose := false 56 | ls := logshim.NewLogShim(logger, logger, verbose) 57 | 58 | err = validator.NewCheckValidator(input).Validate() 59 | if err != nil { 60 | log.Fatalf("Exiting with error: %s", err) 61 | } 62 | 63 | var endpoint string 64 | if input.Source.Endpoint != "" { 65 | endpoint = input.Source.Endpoint 66 | } else { 67 | endpoint = pivnet.DefaultHost 68 | } 69 | 70 | apiToken := input.Source.APIToken 71 | token := pivnet.NewAccessTokenOrLegacyToken(apiToken, endpoint, input.Source.SkipSSLValidation, "Pivnet Resource") 72 | 73 | client := NewPivnetClientWithToken( 74 | token, 75 | endpoint, 76 | input.Source.SkipSSLValidation, 77 | useragent.UserAgent(version, "check", input.Source.ProductSlug), 78 | ls, 79 | ) 80 | 81 | f := filter.NewFilter(ls) 82 | 83 | semverConverter := semver.NewSemverConverter(ls) 84 | s := sorter.NewSorter(ls, semverConverter) 85 | 86 | response, err := check.NewCheckCommand( 87 | ls, 88 | version, 89 | f, 90 | client, 91 | s, 92 | logFile.Name(), 93 | ).Run(input) 94 | if err != nil { 95 | log.Fatalf("Exiting with error: %s", err) 96 | } 97 | 98 | err = json.NewEncoder(os.Stdout).Encode(response) 99 | if err != nil { 100 | log.Fatalf("Exiting with error: %s", err) 101 | } 102 | } 103 | 104 | func NewPivnetClientWithToken(token pivnet.AccessTokenOrLegacyToken, host string, skipSSLValidation bool, userAgent string, logger logger.Logger) *gp.Client { 105 | clientConfig := pivnet.ClientConfig{ 106 | Host: host, 107 | UserAgent: userAgent, 108 | SkipSSLValidation: skipSSLValidation, 109 | } 110 | 111 | return gp.NewClient( 112 | token, 113 | clientConfig, 114 | logger, 115 | ) 116 | } 117 | -------------------------------------------------------------------------------- /cmd/in/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | "os" 7 | 8 | "github.com/fatih/color" 9 | "github.com/pivotal-cf/go-pivnet/v7" 10 | "github.com/pivotal-cf/go-pivnet/v7/logger" 11 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 12 | "github.com/pivotal-cf/go-pivnet/v7/md5sum" 13 | "github.com/pivotal-cf/go-pivnet/v7/sha256sum" 14 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 15 | "github.com/pivotal-cf/pivnet-resource/v3/downloader" 16 | "github.com/pivotal-cf/pivnet-resource/v3/filter" 17 | "github.com/pivotal-cf/pivnet-resource/v3/gp" 18 | "github.com/pivotal-cf/pivnet-resource/v3/in" 19 | "github.com/pivotal-cf/pivnet-resource/v3/in/filesystem" 20 | "github.com/pivotal-cf/pivnet-resource/v3/ui" 21 | "github.com/pivotal-cf/pivnet-resource/v3/useragent" 22 | "github.com/pivotal-cf/pivnet-resource/v3/validator" 23 | "github.com/robdimsdale/sanitizer" 24 | ) 25 | 26 | var ( 27 | // version is deliberately left uninitialized so it can be set at compile-time 28 | version string 29 | ) 30 | 31 | func main() { 32 | if version == "" { 33 | version = "dev" 34 | } 35 | 36 | color.NoColor = false 37 | 38 | logWriter := os.Stderr 39 | uiPrinter := ui.NewUIPrinter(logWriter) 40 | 41 | logger := log.New(logWriter, "", log.LstdFlags) 42 | 43 | logger.Printf("PivNet Resource version: %s", version) 44 | 45 | if len(os.Args) < 2 { 46 | uiPrinter.PrintErrorlnf( 47 | "not enough args - usage: %s ", 48 | os.Args[0], 49 | ) 50 | os.Exit(1) 51 | } 52 | 53 | downloadDir := os.Args[1] 54 | 55 | var input concourse.InRequest 56 | err := json.NewDecoder(os.Stdin).Decode(&input) 57 | if err != nil { 58 | uiPrinter.PrintErrorln(err) 59 | os.Exit(1) 60 | } 61 | 62 | sanitized := concourse.SanitizedSource(input.Source) 63 | logger.SetOutput(sanitizer.NewSanitizer(sanitized, logWriter)) 64 | 65 | verbose := input.Source.Verbose 66 | ls := logshim.NewLogShim(logger, logger, verbose) 67 | 68 | ls.Debug("Verbose output enabled") 69 | logger.Printf("Creating download directory: %s", downloadDir) 70 | 71 | err = os.MkdirAll(downloadDir, os.ModePerm) 72 | if err != nil { 73 | uiPrinter.PrintErrorln(err) 74 | os.Exit(1) 75 | } 76 | 77 | err = validator.NewInValidator(input).Validate() 78 | if err != nil { 79 | uiPrinter.PrintErrorln(err) 80 | os.Exit(1) 81 | } 82 | 83 | var endpoint string 84 | if input.Source.Endpoint != "" { 85 | endpoint = input.Source.Endpoint 86 | } else { 87 | endpoint = pivnet.DefaultHost 88 | } 89 | 90 | apiToken := input.Source.APIToken 91 | token := pivnet.NewAccessTokenOrLegacyToken(apiToken, endpoint, input.Source.SkipSSLValidation, "Pivnet Resource") 92 | 93 | if len(apiToken) < 20 { 94 | uiPrinter.PrintDeprecationln("The use of static Pivnet API tokens is deprecated and will be removed. Please see https://network.pivotal.io/docs/api#how-to-authenticate for details.") 95 | } 96 | 97 | client := NewPivnetClientWithToken( 98 | token, 99 | endpoint, 100 | input.Source.SkipSSLValidation, 101 | useragent.UserAgent(version, "get", input.Source.ProductSlug), 102 | ls, 103 | ) 104 | 105 | d := downloader.NewDownloader(client, downloadDir, ls, logWriter) 106 | 107 | fs := sha256sum.NewFileSummer() 108 | md5fs := md5sum.NewFileSummer() 109 | 110 | f := filter.NewFilter(ls) 111 | 112 | fileWriter := filesystem.NewFileWriter(downloadDir, ls) 113 | archive := &in.Archive{} 114 | 115 | response, err := in.NewInCommand( 116 | ls, 117 | client, 118 | f, 119 | d, 120 | fs, 121 | md5fs, 122 | fileWriter, 123 | archive, 124 | ).Run(input) 125 | if err != nil { 126 | uiPrinter.PrintErrorln(err) 127 | os.Exit(1) 128 | } 129 | 130 | err = json.NewEncoder(os.Stdout).Encode(response) 131 | if err != nil { 132 | uiPrinter.PrintErrorln(err) 133 | os.Exit(1) 134 | } 135 | } 136 | 137 | func NewPivnetClientWithToken(token pivnet.AccessTokenService, host string, skipSSLValidation bool, userAgent string, logger logger.Logger) *gp.Client { 138 | clientConfig := pivnet.ClientConfig{ 139 | Host: host, 140 | UserAgent: userAgent, 141 | SkipSSLValidation: skipSSLValidation, 142 | } 143 | 144 | return gp.NewClient( 145 | token, 146 | clientConfig, 147 | logger, 148 | ) 149 | } 150 | -------------------------------------------------------------------------------- /concourse/sanitized_input.go: -------------------------------------------------------------------------------- 1 | package concourse 2 | 3 | func SanitizedSource(source Source) map[string]string { 4 | s := make(map[string]string) 5 | 6 | if source.APIToken != "" { 7 | s[source.APIToken] = "***REDACTED-PIVNET_API_TOKEN***" 8 | } 9 | 10 | return s 11 | } 12 | -------------------------------------------------------------------------------- /concourse/types.go: -------------------------------------------------------------------------------- 1 | package concourse 2 | 3 | type SortBy string 4 | 5 | const ( 6 | SortByNone SortBy = "none" 7 | SortBySemver SortBy = "semver" 8 | SortByLastUpdated SortBy = "last_updated" 9 | ) 10 | 11 | type Source struct { 12 | APIToken string `json:"api_token"` 13 | ProductSlug string `json:"product_slug"` 14 | ProductVersion string `json:"product_version"` 15 | Endpoint string `json:"endpoint"` 16 | ReleaseType string `json:"release_type"` 17 | SortBy SortBy `json:"sort_by"` 18 | SkipSSLValidation bool `json:"skip_ssl_verification"` 19 | CopyMetadata bool `json:"copy_metadata"` 20 | Verbose bool `json:"verbose"` 21 | } 22 | 23 | type CheckRequest struct { 24 | Source Source `json:"source"` 25 | Version Version `json:"version"` 26 | } 27 | 28 | type Version struct { 29 | ProductVersion string `json:"product_version"` 30 | } 31 | 32 | type CheckResponse []Version 33 | 34 | type InRequest struct { 35 | Source Source `json:"source"` 36 | Version Version `json:"version"` 37 | Params InParams `json:"params"` 38 | } 39 | 40 | type InParams struct { 41 | Globs []string `json:"globs"` 42 | Unpack bool `json:"unpack"` 43 | } 44 | 45 | type InResponse struct { 46 | Version Version `json:"version"` 47 | Metadata []Metadata `json:"metadata,omitempty"` 48 | } 49 | 50 | type Metadata struct { 51 | Name string `json:"name,omitempty"` 52 | Value string `json:"value,omitempty"` 53 | } 54 | 55 | type OutRequest struct { 56 | Params OutParams `json:"params"` 57 | Source Source `json:"source"` 58 | } 59 | 60 | type OutParams struct { 61 | FileGlob string `json:"file_glob"` 62 | MetadataFile string `json:"metadata_file"` 63 | SkipProductFilePolling bool `json:"skip_product_file_polling"` 64 | Override bool `json:"override"` 65 | } 66 | 67 | type OutResponse struct { 68 | Version Version `json:"version"` 69 | Metadata []Metadata `json:"metadata,omitempty"` 70 | } 71 | -------------------------------------------------------------------------------- /downloader/downloader.go: -------------------------------------------------------------------------------- 1 | package downloader 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | 10 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 11 | "github.com/pivotal-cf/go-pivnet/v7/download" 12 | "github.com/pivotal-cf/go-pivnet/v7/logger" 13 | ) 14 | 15 | //counterfeiter:generate --fake-name FakeClient . client 16 | type client interface { 17 | DownloadProductFile(writer *download.FileInfo, productSlug string, releaseID int, productFileID int, progressWriter io.Writer) error 18 | } 19 | 20 | type Downloader struct { 21 | client client 22 | downloadDir string 23 | logger logger.Logger 24 | progressWriter io.Writer 25 | } 26 | 27 | func NewDownloader( 28 | client client, 29 | downloadDir string, 30 | logger logger.Logger, 31 | progressWriter io.Writer, 32 | ) *Downloader { 33 | return &Downloader{ 34 | client: client, 35 | downloadDir: downloadDir, 36 | logger: logger, 37 | progressWriter: progressWriter, 38 | } 39 | } 40 | 41 | func (d Downloader) Download( 42 | pfs []pivnet.ProductFile, 43 | productSlug string, 44 | releaseID int, 45 | ) ([]string, error) { 46 | d.logger.Debug("Ensuring download directory exists") 47 | 48 | err := os.MkdirAll(d.downloadDir, os.ModePerm) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | var fileNames []string 54 | for _, pf := range pfs { 55 | parts := strings.Split(pf.AWSObjectKey, "/") 56 | fileName := parts[len(parts)-1] 57 | 58 | downloadPath := filepath.Join(d.downloadDir, fileName) 59 | 60 | d.logger.Debug(fmt.Sprintf("Creating file: '%s'", downloadPath)) 61 | file, err := os.Create(downloadPath) 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | fileInfo, err := download.NewFileInfo(file) 67 | if err != nil { 68 | return nil, err 69 | } 70 | 71 | d.logger.Info(fmt.Sprintf( 72 | "Downloading: '%s' to file: '%s'", 73 | pf.Name, 74 | downloadPath, 75 | )) 76 | 77 | err = d.client.DownloadProductFile(fileInfo, productSlug, releaseID, pf.ID, d.progressWriter) 78 | if err != nil { 79 | d.logger.Info(fmt.Sprintf("Download failed: %s", 80 | err.Error(), 81 | )) 82 | return nil, err 83 | } 84 | fileNames = append(fileNames, downloadPath) 85 | } 86 | 87 | return fileNames, nil 88 | } 89 | -------------------------------------------------------------------------------- /downloader/downloader_suite_test.go: -------------------------------------------------------------------------------- 1 | package downloader_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestDownloader(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Downloader Suite") 13 | } 14 | -------------------------------------------------------------------------------- /downloader/downloaderfakes/fake_client.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package downloaderfakes 3 | 4 | import ( 5 | "io" 6 | "sync" 7 | 8 | "github.com/pivotal-cf/go-pivnet/v7/download" 9 | ) 10 | 11 | type FakeClient struct { 12 | DownloadProductFileStub func(*download.FileInfo, string, int, int, io.Writer) error 13 | downloadProductFileMutex sync.RWMutex 14 | downloadProductFileArgsForCall []struct { 15 | arg1 *download.FileInfo 16 | arg2 string 17 | arg3 int 18 | arg4 int 19 | arg5 io.Writer 20 | } 21 | downloadProductFileReturns struct { 22 | result1 error 23 | } 24 | downloadProductFileReturnsOnCall map[int]struct { 25 | result1 error 26 | } 27 | invocations map[string][][]interface{} 28 | invocationsMutex sync.RWMutex 29 | } 30 | 31 | func (fake *FakeClient) DownloadProductFile(arg1 *download.FileInfo, arg2 string, arg3 int, arg4 int, arg5 io.Writer) error { 32 | fake.downloadProductFileMutex.Lock() 33 | ret, specificReturn := fake.downloadProductFileReturnsOnCall[len(fake.downloadProductFileArgsForCall)] 34 | fake.downloadProductFileArgsForCall = append(fake.downloadProductFileArgsForCall, struct { 35 | arg1 *download.FileInfo 36 | arg2 string 37 | arg3 int 38 | arg4 int 39 | arg5 io.Writer 40 | }{arg1, arg2, arg3, arg4, arg5}) 41 | stub := fake.DownloadProductFileStub 42 | fakeReturns := fake.downloadProductFileReturns 43 | fake.recordInvocation("DownloadProductFile", []interface{}{arg1, arg2, arg3, arg4, arg5}) 44 | fake.downloadProductFileMutex.Unlock() 45 | if stub != nil { 46 | return stub(arg1, arg2, arg3, arg4, arg5) 47 | } 48 | if specificReturn { 49 | return ret.result1 50 | } 51 | return fakeReturns.result1 52 | } 53 | 54 | func (fake *FakeClient) DownloadProductFileCallCount() int { 55 | fake.downloadProductFileMutex.RLock() 56 | defer fake.downloadProductFileMutex.RUnlock() 57 | return len(fake.downloadProductFileArgsForCall) 58 | } 59 | 60 | func (fake *FakeClient) DownloadProductFileCalls(stub func(*download.FileInfo, string, int, int, io.Writer) error) { 61 | fake.downloadProductFileMutex.Lock() 62 | defer fake.downloadProductFileMutex.Unlock() 63 | fake.DownloadProductFileStub = stub 64 | } 65 | 66 | func (fake *FakeClient) DownloadProductFileArgsForCall(i int) (*download.FileInfo, string, int, int, io.Writer) { 67 | fake.downloadProductFileMutex.RLock() 68 | defer fake.downloadProductFileMutex.RUnlock() 69 | argsForCall := fake.downloadProductFileArgsForCall[i] 70 | return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5 71 | } 72 | 73 | func (fake *FakeClient) DownloadProductFileReturns(result1 error) { 74 | fake.downloadProductFileMutex.Lock() 75 | defer fake.downloadProductFileMutex.Unlock() 76 | fake.DownloadProductFileStub = nil 77 | fake.downloadProductFileReturns = struct { 78 | result1 error 79 | }{result1} 80 | } 81 | 82 | func (fake *FakeClient) DownloadProductFileReturnsOnCall(i int, result1 error) { 83 | fake.downloadProductFileMutex.Lock() 84 | defer fake.downloadProductFileMutex.Unlock() 85 | fake.DownloadProductFileStub = nil 86 | if fake.downloadProductFileReturnsOnCall == nil { 87 | fake.downloadProductFileReturnsOnCall = make(map[int]struct { 88 | result1 error 89 | }) 90 | } 91 | fake.downloadProductFileReturnsOnCall[i] = struct { 92 | result1 error 93 | }{result1} 94 | } 95 | 96 | func (fake *FakeClient) Invocations() map[string][][]interface{} { 97 | fake.invocationsMutex.RLock() 98 | defer fake.invocationsMutex.RUnlock() 99 | fake.downloadProductFileMutex.RLock() 100 | defer fake.downloadProductFileMutex.RUnlock() 101 | copiedInvocations := map[string][][]interface{}{} 102 | for key, value := range fake.invocations { 103 | copiedInvocations[key] = value 104 | } 105 | return copiedInvocations 106 | } 107 | 108 | func (fake *FakeClient) recordInvocation(key string, args []interface{}) { 109 | fake.invocationsMutex.Lock() 110 | defer fake.invocationsMutex.Unlock() 111 | if fake.invocations == nil { 112 | fake.invocations = map[string][][]interface{}{} 113 | } 114 | if fake.invocations[key] == nil { 115 | fake.invocations[key] = [][]interface{}{} 116 | } 117 | fake.invocations[key] = append(fake.invocations[key], args) 118 | } 119 | -------------------------------------------------------------------------------- /downloader/downloaderfakes/fake_extended_client.go: -------------------------------------------------------------------------------- 1 | // This file was generated by counterfeiter 2 | package downloaderfakes 3 | 4 | import ( 5 | "io" 6 | "sync" 7 | ) 8 | 9 | type FakeExtendedClient struct { 10 | DownloadFileStub func(writer io.Writer, downloadLink string) error 11 | downloadFileMutex sync.RWMutex 12 | downloadFileArgsForCall []struct { 13 | writer io.Writer 14 | downloadLink string 15 | } 16 | downloadFileReturns struct { 17 | result1 error 18 | } 19 | invocations map[string][][]interface{} 20 | invocationsMutex sync.RWMutex 21 | } 22 | 23 | func (fake *FakeExtendedClient) DownloadFile(writer io.Writer, downloadLink string) error { 24 | fake.downloadFileMutex.Lock() 25 | fake.downloadFileArgsForCall = append(fake.downloadFileArgsForCall, struct { 26 | writer io.Writer 27 | downloadLink string 28 | }{writer, downloadLink}) 29 | fake.recordInvocation("DownloadFile", []interface{}{writer, downloadLink}) 30 | fake.downloadFileMutex.Unlock() 31 | if fake.DownloadFileStub != nil { 32 | return fake.DownloadFileStub(writer, downloadLink) 33 | } else { 34 | return fake.downloadFileReturns.result1 35 | } 36 | } 37 | 38 | func (fake *FakeExtendedClient) DownloadFileCallCount() int { 39 | fake.downloadFileMutex.RLock() 40 | defer fake.downloadFileMutex.RUnlock() 41 | return len(fake.downloadFileArgsForCall) 42 | } 43 | 44 | func (fake *FakeExtendedClient) DownloadFileArgsForCall(i int) (io.Writer, string) { 45 | fake.downloadFileMutex.RLock() 46 | defer fake.downloadFileMutex.RUnlock() 47 | return fake.downloadFileArgsForCall[i].writer, fake.downloadFileArgsForCall[i].downloadLink 48 | } 49 | 50 | func (fake *FakeExtendedClient) DownloadFileReturns(result1 error) { 51 | fake.DownloadFileStub = nil 52 | fake.downloadFileReturns = struct { 53 | result1 error 54 | }{result1} 55 | } 56 | 57 | func (fake *FakeExtendedClient) Invocations() map[string][][]interface{} { 58 | fake.invocationsMutex.RLock() 59 | defer fake.invocationsMutex.RUnlock() 60 | fake.downloadFileMutex.RLock() 61 | defer fake.downloadFileMutex.RUnlock() 62 | return fake.invocations 63 | } 64 | 65 | func (fake *FakeExtendedClient) recordInvocation(key string, args []interface{}) { 66 | fake.invocationsMutex.Lock() 67 | defer fake.invocationsMutex.Unlock() 68 | if fake.invocations == nil { 69 | fake.invocations = map[string][][]interface{}{} 70 | } 71 | if fake.invocations[key] == nil { 72 | fake.invocations[key] = [][]interface{}{} 73 | } 74 | fake.invocations[key] = append(fake.invocations[key], args) 75 | } 76 | -------------------------------------------------------------------------------- /downloader/package.go: -------------------------------------------------------------------------------- 1 | package downloader 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Pivnet Resource Examples 2 | 3 | This directory contains example pipeline configurations for common scenarios. 4 | -------------------------------------------------------------------------------- /examples/get-aws-vsphere-stemcells.yml: -------------------------------------------------------------------------------- 1 | --- 2 | resource_types: 3 | - name: pivnet 4 | type: docker-image 5 | source: 6 | repository: pivotalcf/pivnet-resource 7 | tag: latest-final 8 | 9 | resources: 10 | - name: stemcells 11 | type: pivnet 12 | source: 13 | api_token: my-api-token 14 | product_slug: stemcells 15 | 16 | jobs: 17 | - name: download-aws-and-vsphere-stemcells 18 | plan: 19 | - get: stemcells 20 | params: 21 | globs: 22 | - "*aws*" 23 | - "*vsphere*" 24 | 25 | -------------------------------------------------------------------------------- /examples/put-p-mysql.yml: -------------------------------------------------------------------------------- 1 | --- 2 | resource_types: 3 | - name: pivnet 4 | type: docker-image 5 | source: 6 | repository: pivotalcf/pivnet-resource 7 | tag: latest-final 8 | 9 | resources: 10 | - name: p-mysql 11 | type: pivnet 12 | source: 13 | api_token: my-api-token 14 | product_slug: p-mysql 15 | 16 | jobs: 17 | - name: create-p-mysql-pivnet 18 | plan: 19 | - put: p-mysql 20 | params: 21 | metadata_file: relative/path/to/some-metadata-file 22 | file_glob: relative/path/to/some-source-files/* 23 | -------------------------------------------------------------------------------- /filter/filter.go: -------------------------------------------------------------------------------- 1 | package filter 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "regexp" 7 | "strings" 8 | 9 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 10 | "github.com/pivotal-cf/go-pivnet/v7/logger" 11 | ) 12 | 13 | type Filter struct { 14 | l logger.Logger 15 | } 16 | 17 | func NewFilter(l logger.Logger) *Filter { 18 | return &Filter{ 19 | l: l, 20 | } 21 | } 22 | 23 | func (f Filter) ReleasesByReleaseType(releases []pivnet.Release, releaseType pivnet.ReleaseType) ([]pivnet.Release, error) { 24 | filteredReleases := make([]pivnet.Release, 0) 25 | 26 | for _, release := range releases { 27 | if release.ReleaseType == releaseType { 28 | filteredReleases = append(filteredReleases, release) 29 | } 30 | } 31 | 32 | return filteredReleases, nil 33 | } 34 | 35 | // ReleasesByVersion returns all releases that match the provided version regex 36 | func (f Filter) ReleasesByVersion(releases []pivnet.Release, version string) ([]pivnet.Release, error) { 37 | filteredReleases := make([]pivnet.Release, 0) 38 | 39 | for _, release := range releases { 40 | match, err := regexp.MatchString(version, release.Version) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | if match { 46 | filteredReleases = append(filteredReleases, release) 47 | } 48 | } 49 | 50 | return filteredReleases, nil 51 | } 52 | 53 | func (f Filter) ProductFileKeysByGlobs( 54 | productFiles []pivnet.ProductFile, 55 | globs []string, 56 | ) ([]pivnet.ProductFile, error) { 57 | f.l.Debug("filter.ProductFilesKeysByGlobs", logger.Data{"globs": globs}) 58 | 59 | filtered := []pivnet.ProductFile{} 60 | for _, pattern := range globs { 61 | for _, p := range productFiles { 62 | parts := strings.Split(p.AWSObjectKey, "/") 63 | fileName := parts[len(parts)-1] 64 | 65 | matched, err := filepath.Match(pattern, fileName) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | if matched { 71 | filtered = append(filtered, p) 72 | } 73 | } 74 | 75 | } 76 | 77 | if len(filtered) == 0 && len(globs) != 0 { 78 | return nil, fmt.Errorf("no match for glob(s): '%s'", strings.Join(globs, ", ")) 79 | } 80 | 81 | return filtered, nil 82 | } 83 | -------------------------------------------------------------------------------- /filter/filter_suite_test.go: -------------------------------------------------------------------------------- 1 | package filter_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestFilter(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Filter Suite") 13 | } 14 | -------------------------------------------------------------------------------- /globs/globs.go: -------------------------------------------------------------------------------- 1 | package globs 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | ) 9 | 10 | type Globber struct { 11 | fileGlob string 12 | sourcesDir string 13 | 14 | logger logger.Logger 15 | } 16 | 17 | type GlobberConfig struct { 18 | FileGlob string 19 | SourcesDir string 20 | 21 | Logger logger.Logger 22 | } 23 | 24 | func NewGlobber(config GlobberConfig) *Globber { 25 | return &Globber{ 26 | fileGlob: config.FileGlob, 27 | sourcesDir: config.SourcesDir, 28 | 29 | logger: config.Logger, 30 | } 31 | } 32 | 33 | func (g Globber) ExactGlobs() ([]string, error) { 34 | matches, err := filepath.Glob(filepath.Join(g.sourcesDir, g.fileGlob)) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | if len(matches) == 0 { 40 | return nil, fmt.Errorf("no matches found for pattern: '%s'", g.fileGlob) 41 | } 42 | 43 | absPathSourcesDir, err := filepath.Abs(g.sourcesDir) 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | exactGlobs := []string{} 49 | for _, match := range matches { 50 | absPath, err := filepath.Abs(match) 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | exactGlob, err := filepath.Rel(absPathSourcesDir, absPath) 56 | if err != nil { 57 | panic(err) 58 | } 59 | 60 | exactGlobs = append(exactGlobs, exactGlob) 61 | } 62 | 63 | return exactGlobs, nil 64 | } 65 | -------------------------------------------------------------------------------- /globs/globs_suite_test.go: -------------------------------------------------------------------------------- 1 | package globs_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestGlobs(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Globs Suite") 13 | } 14 | -------------------------------------------------------------------------------- /globs/globs_test.go: -------------------------------------------------------------------------------- 1 | package globs_test 2 | 3 | import ( 4 | "io/ioutil" 5 | "log" 6 | "os" 7 | "path/filepath" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | "github.com/pivotal-cf/go-pivnet/v7/logger" 12 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 13 | "github.com/pivotal-cf/pivnet-resource/v3/globs" 14 | ) 15 | 16 | var _ = Describe("Globber", func() { 17 | Describe("ExactGlobs", func() { 18 | var ( 19 | fakeLogger logger.Logger 20 | 21 | globberConfig globs.GlobberConfig 22 | globber *globs.Globber 23 | 24 | tempDir string 25 | myFilesDir string 26 | ) 27 | 28 | BeforeEach(func() { 29 | var err error 30 | tempDir, err = ioutil.TempDir("", "pivnet-resource") 31 | Expect(err).NotTo(HaveOccurred()) 32 | 33 | myFilesDir = filepath.Join(tempDir, "my_files") 34 | err = os.Mkdir(myFilesDir, os.ModePerm) 35 | Expect(err).NotTo(HaveOccurred()) 36 | 37 | _, err = os.Create(filepath.Join(myFilesDir, "file-0")) 38 | Expect(err).NotTo(HaveOccurred()) 39 | 40 | logger := log.New(GinkgoWriter, "", log.LstdFlags) 41 | fakeLogger = logshim.NewLogShim(logger, logger, true) 42 | 43 | globberConfig = globs.GlobberConfig{ 44 | FileGlob: "my_files/*", 45 | SourcesDir: tempDir, 46 | Logger: fakeLogger, 47 | } 48 | 49 | globber = globs.NewGlobber(globberConfig) 50 | }) 51 | 52 | AfterEach(func() { 53 | err := os.RemoveAll(tempDir) 54 | Expect(err).NotTo(HaveOccurred()) 55 | }) 56 | 57 | Context("when no files match the fileglob", func() { 58 | BeforeEach(func() { 59 | globberConfig.FileGlob = "this-will-match-nothing" 60 | globber = globs.NewGlobber(globberConfig) 61 | }) 62 | 63 | It("returns an error", func() { 64 | _, err := globber.ExactGlobs() 65 | Expect(err).To(HaveOccurred()) 66 | 67 | Expect(err.Error()).To(ContainSubstring("no matches")) 68 | }) 69 | }) 70 | 71 | Context("when multiple files match the fileglob", func() { 72 | BeforeEach(func() { 73 | _, err := os.Create(filepath.Join(myFilesDir, "file-1")) 74 | Expect(err).NotTo(HaveOccurred()) 75 | }) 76 | 77 | It("returns a map of filenames to remote paths", func() { 78 | filenamePaths, err := globber.ExactGlobs() 79 | Expect(err).NotTo(HaveOccurred()) 80 | 81 | Expect(len(filenamePaths)).To(Equal(2)) 82 | 83 | Expect(filenamePaths[0]).To(Equal("my_files/file-0")) 84 | Expect(filenamePaths[1]).To(Equal("my_files/file-1")) 85 | }) 86 | }) 87 | }) 88 | }) 89 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pivotal-cf/pivnet-resource/v3 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/blang/semver v3.5.1+incompatible 7 | github.com/concourse/s3-resource v1.0.0 8 | github.com/fatih/color v1.7.0 9 | github.com/h2non/filetype v0.0.0-20180111114405-3af83f124ffa 10 | github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 11 | github.com/onsi/ginkgo v1.12.0 12 | github.com/onsi/gomega v1.26.0 13 | github.com/pivotal-cf/go-pivnet/v7 v7.0.1 14 | github.com/robdimsdale/sanitizer v0.0.0-20160522134901-ab2334cb7539 15 | gopkg.in/yaml.v2 v2.2.4 16 | ) 17 | 18 | require ( 19 | github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f // indirect 20 | github.com/aws/aws-sdk-go v0.0.0-20171017211306-a28db88bdcd8 // indirect 21 | github.com/cheggaaa/pb v1.0.26 // indirect 22 | github.com/davecgh/go-spew v1.1.1 // indirect 23 | github.com/go-ini/ini v1.39.0 // indirect 24 | github.com/go-ole/go-ole v1.2.1 // indirect 25 | github.com/google/go-cmp v0.5.9 // indirect 26 | github.com/gopherjs/gopherjs v0.0.0-20171016203739-a0a7cfed7b2a // indirect 27 | github.com/hpcloud/tail v1.0.0 // indirect 28 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect 29 | github.com/jtolds/gls v4.2.1+incompatible // indirect 30 | github.com/mattn/go-colorable v0.0.9 // indirect 31 | github.com/mattn/go-isatty v0.0.4 // indirect 32 | github.com/mattn/go-runewidth v0.0.3 // indirect 33 | github.com/mitchellh/colorstring v0.0.0-20150917214807-8631ce90f286 // indirect 34 | github.com/pmezard/go-difflib v1.0.0 // indirect 35 | github.com/shirou/gopsutil v2.17.12+incompatible // indirect 36 | github.com/smartystreets/assertions v0.0.0-20170925172151-0b37b35ec743 // indirect 37 | github.com/smartystreets/goconvey v0.0.0-20170825221426-e5b2b7c91115 // indirect 38 | github.com/stretchr/testify v0.0.0-20171018052257-2aa2c176b9da // indirect 39 | golang.org/x/mod v0.7.0 // indirect 40 | golang.org/x/net v0.5.0 // indirect 41 | golang.org/x/sync v0.1.0 // indirect 42 | golang.org/x/sys v0.4.0 // indirect 43 | golang.org/x/text v0.6.0 // indirect 44 | golang.org/x/tools v0.5.0 // indirect 45 | gopkg.in/cheggaaa/pb.v1 v1.0.26 // indirect 46 | gopkg.in/fsnotify.v1 v1.4.7 // indirect 47 | gopkg.in/h2non/filetype.v1 v1.0.5 // indirect 48 | gopkg.in/ini.v1 v1.39.0 // indirect 49 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 50 | gopkg.in/yaml.v3 v3.0.1 // indirect 51 | ) 52 | -------------------------------------------------------------------------------- /in/archive.go: -------------------------------------------------------------------------------- 1 | package in 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "strings" 12 | 13 | "github.com/h2non/filetype" 14 | ) 15 | 16 | var archiveMimetypes = []string{ 17 | "application/x-gzip", 18 | "application/gzip", 19 | "application/x-tar", 20 | "application/zip", 21 | } 22 | 23 | type Archive struct{} 24 | 25 | func (a *Archive) Mimetype(filename string) string { 26 | f, err := os.Open(filename) 27 | if err != nil { 28 | return "" 29 | } 30 | defer f.Close() 31 | 32 | mime, err := mimetype(bufio.NewReader(f)) 33 | if err != nil { 34 | return "" 35 | } 36 | 37 | for i := range archiveMimetypes { 38 | if strings.HasPrefix(mime, archiveMimetypes[i]) { 39 | return archiveMimetypes[i] 40 | } 41 | } 42 | 43 | return "" 44 | } 45 | 46 | func (a *Archive) Extract(mime, filename string) error { 47 | destDir := filepath.Dir(filename) 48 | 49 | err := inflate(mime, filename, destDir) 50 | if err != nil { 51 | return fmt.Errorf("failed to extract archive: %s with mimetype %s", err.Error(), mime) 52 | } 53 | 54 | if mime == "application/gzip" || mime == "application/x-gzip" { 55 | fileInfos, err := ioutil.ReadDir(destDir) 56 | if err != nil { 57 | return fmt.Errorf("failed to read dir: %s", err) 58 | } 59 | 60 | if len(fileInfos) != 1 { 61 | return fmt.Errorf("%d files found after gunzip; expected 1", len(fileInfos)) 62 | } 63 | 64 | filename = filepath.Join(destDir, fileInfos[0].Name()) 65 | mime = a.Mimetype(filename) 66 | if mime == "application/x-tar" { 67 | err = inflate(mime, filename, destDir) 68 | if err != nil { 69 | return fmt.Errorf("failed to extract archive x-tar: %s", err.Error()) 70 | } 71 | } 72 | } 73 | 74 | return nil 75 | } 76 | 77 | func inflate(mime, path, destination string) error { 78 | var cmd *exec.Cmd 79 | 80 | switch mime { 81 | case "application/zip": 82 | cmd = exec.Command("unzip", "-d", destination, path) 83 | defer os.Remove(path) 84 | 85 | case "application/x-tar": 86 | cmd = exec.Command("tar", "xf", path, "-C", destination) 87 | defer os.Remove(path) 88 | 89 | case "application/gzip", "application/x-gzip": 90 | cmd = exec.Command("gunzip", path) 91 | 92 | default: 93 | return fmt.Errorf("don't know how to extract %s", mime) 94 | } 95 | 96 | return cmd.Run() 97 | } 98 | 99 | func mimetype(r *bufio.Reader) (string, error) { 100 | bs, err := r.Peek(512) 101 | if err != nil && err != io.EOF { 102 | return "", err 103 | } 104 | 105 | kind, err := filetype.Match(bs) 106 | if err != nil { 107 | return "", err 108 | } 109 | 110 | return kind.MIME.Value, nil 111 | } 112 | -------------------------------------------------------------------------------- /in/filesystem/filesystem_command_test.go: -------------------------------------------------------------------------------- 1 | package filesystem_test 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "log" 7 | "os" 8 | "path/filepath" 9 | 10 | "gopkg.in/yaml.v2" 11 | 12 | "github.com/pivotal-cf/go-pivnet/v7/logger" 13 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 14 | "github.com/pivotal-cf/pivnet-resource/v3/in/filesystem" 15 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 16 | 17 | . "github.com/onsi/ginkgo" 18 | . "github.com/onsi/gomega" 19 | ) 20 | 21 | var _ = Describe("FileWriter", func() { 22 | var ( 23 | fileWriter *filesystem.FileWriter 24 | downloadDir string 25 | fakeLogger logger.Logger 26 | ) 27 | 28 | BeforeEach(func() { 29 | var err error 30 | downloadDir, err = ioutil.TempDir("", "") 31 | Expect(err).NotTo(HaveOccurred()) 32 | 33 | logger := log.New(GinkgoWriter, "", log.LstdFlags) 34 | fakeLogger = logshim.NewLogShim(logger, logger, true) 35 | 36 | fileWriter = filesystem.NewFileWriter(downloadDir, fakeLogger) 37 | }) 38 | 39 | AfterEach(func() { 40 | err := os.RemoveAll(downloadDir) 41 | Expect(err).NotTo(HaveOccurred()) 42 | }) 43 | 44 | Describe("WriteVersionFile", func() { 45 | It("writes version file", func() { 46 | err := fileWriter.WriteVersionFile("some-version") 47 | Expect(err).NotTo(HaveOccurred()) 48 | 49 | expectedVersionFilepath := filepath.Join(downloadDir, "version") 50 | b, err := ioutil.ReadFile(expectedVersionFilepath) 51 | Expect(err).NotTo(HaveOccurred()) 52 | 53 | Expect(b).To(Equal([]byte("some-version"))) 54 | }) 55 | }) 56 | 57 | Describe("WriteMetadataJSONFile", func() { 58 | It("writes metadata file in json format", func() { 59 | inputMetadata := metadata.Metadata{ 60 | Release: &metadata.Release{ 61 | Version: "some version", 62 | ReleaseType: "some release type", 63 | }, 64 | } 65 | 66 | err := fileWriter.WriteMetadataJSONFile(inputMetadata) 67 | Expect(err).NotTo(HaveOccurred()) 68 | 69 | expectedVersionFilepath := filepath.Join(downloadDir, "metadata.json") 70 | b, err := ioutil.ReadFile(expectedVersionFilepath) 71 | Expect(err).NotTo(HaveOccurred()) 72 | 73 | var unmarshalledMetadata metadata.Metadata 74 | err = json.Unmarshal(b, &unmarshalledMetadata) 75 | Expect(err).NotTo(HaveOccurred()) 76 | 77 | Expect(unmarshalledMetadata).To(Equal(inputMetadata)) 78 | }) 79 | }) 80 | 81 | Describe("WriteMetadataYAMLFile", func() { 82 | It("writes metadata file in yaml format", func() { 83 | inputMetadata := metadata.Metadata{ 84 | Release: &metadata.Release{ 85 | Version: "some version", 86 | ReleaseType: "some release type", 87 | }, 88 | } 89 | 90 | err := fileWriter.WriteMetadataYAMLFile(inputMetadata) 91 | Expect(err).NotTo(HaveOccurred()) 92 | 93 | expectedVersionFilepath := filepath.Join(downloadDir, "metadata.yaml") 94 | b, err := ioutil.ReadFile(expectedVersionFilepath) 95 | Expect(err).NotTo(HaveOccurred()) 96 | 97 | var unmarshalledMetadata metadata.Metadata 98 | err = yaml.Unmarshal(b, &unmarshalledMetadata) 99 | Expect(err).NotTo(HaveOccurred()) 100 | 101 | Expect(unmarshalledMetadata).To(Equal(inputMetadata)) 102 | }) 103 | }) 104 | }) 105 | -------------------------------------------------------------------------------- /in/filesystem/filesystem_suite_test.go: -------------------------------------------------------------------------------- 1 | package filesystem_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | const ( 11 | productSlug = "some-product-name" 12 | ) 13 | 14 | func TestInFilesystem(t *testing.T) { 15 | RegisterFailHandler(Fail) 16 | RunSpecs(t, "In Filesystem Suite") 17 | } 18 | -------------------------------------------------------------------------------- /in/filesystem/filewriter.go: -------------------------------------------------------------------------------- 1 | package filesystem 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/pivotal-cf/go-pivnet/v7/logger" 10 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 11 | "gopkg.in/yaml.v2" 12 | ) 13 | 14 | type FileWriter struct { 15 | downloadDir string 16 | logger logger.Logger 17 | } 18 | 19 | func NewFileWriter(downloadDir string, logger logger.Logger) *FileWriter { 20 | return &FileWriter{ 21 | downloadDir: downloadDir, 22 | logger: logger, 23 | } 24 | } 25 | 26 | func (w FileWriter) WriteMetadataYAMLFile(mdata metadata.Metadata) error { 27 | yamlMetadataFilepath := filepath.Join(w.downloadDir, "metadata.yaml") 28 | w.logger.Debug("Writing metadata to yaml file") 29 | 30 | yamlMetadata, err := yaml.Marshal(mdata) 31 | if err != nil { 32 | // Untested as it is too hard to force yaml.Marshal to return an error 33 | return err 34 | } 35 | 36 | err = ioutil.WriteFile(yamlMetadataFilepath, yamlMetadata, os.ModePerm) 37 | if err != nil { 38 | // Untested as it is too hard to force io.WriteFile to return an error 39 | return err 40 | } 41 | 42 | return nil 43 | } 44 | 45 | func (w FileWriter) WriteMetadataJSONFile(mdata metadata.Metadata) error { 46 | jsonMetadataFilepath := filepath.Join(w.downloadDir, "metadata.json") 47 | w.logger.Debug("Writing metadata to json file") 48 | 49 | jsonMetadata, err := json.Marshal(mdata) 50 | if err != nil { 51 | // Untested as it is too hard to force json.Marshal to return an error 52 | return err 53 | } 54 | 55 | err = ioutil.WriteFile(jsonMetadataFilepath, jsonMetadata, os.ModePerm) 56 | if err != nil { 57 | // Untested as it is too hard to force io.WriteFile to return an error 58 | return err 59 | } 60 | 61 | return nil 62 | } 63 | 64 | func (w FileWriter) WriteVersionFile(version string) error { 65 | versionFilepath := filepath.Join(w.downloadDir, "version") 66 | 67 | w.logger.Debug("Writing version to file") 68 | 69 | err := ioutil.WriteFile(versionFilepath, []byte(version), os.ModePerm) 70 | if err != nil { 71 | // Untested as it is too hard to force io.WriteFile to return an error 72 | return err 73 | } 74 | 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /in/in_suite_test.go: -------------------------------------------------------------------------------- 1 | package in_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | const ( 11 | productSlug = "some-product-name" 12 | ) 13 | 14 | func TestIn(t *testing.T) { 15 | RegisterFailHandler(Fail) 16 | RunSpecs(t, "In Suite") 17 | } 18 | -------------------------------------------------------------------------------- /in/infakes/fake_downloader.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package infakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type FakeDownloader struct { 11 | DownloadStub func([]pivnet.ProductFile, string, int) ([]string, error) 12 | downloadMutex sync.RWMutex 13 | downloadArgsForCall []struct { 14 | arg1 []pivnet.ProductFile 15 | arg2 string 16 | arg3 int 17 | } 18 | downloadReturns struct { 19 | result1 []string 20 | result2 error 21 | } 22 | downloadReturnsOnCall map[int]struct { 23 | result1 []string 24 | result2 error 25 | } 26 | invocations map[string][][]interface{} 27 | invocationsMutex sync.RWMutex 28 | } 29 | 30 | func (fake *FakeDownloader) Download(arg1 []pivnet.ProductFile, arg2 string, arg3 int) ([]string, error) { 31 | var arg1Copy []pivnet.ProductFile 32 | if arg1 != nil { 33 | arg1Copy = make([]pivnet.ProductFile, len(arg1)) 34 | copy(arg1Copy, arg1) 35 | } 36 | fake.downloadMutex.Lock() 37 | ret, specificReturn := fake.downloadReturnsOnCall[len(fake.downloadArgsForCall)] 38 | fake.downloadArgsForCall = append(fake.downloadArgsForCall, struct { 39 | arg1 []pivnet.ProductFile 40 | arg2 string 41 | arg3 int 42 | }{arg1Copy, arg2, arg3}) 43 | stub := fake.DownloadStub 44 | fakeReturns := fake.downloadReturns 45 | fake.recordInvocation("Download", []interface{}{arg1Copy, arg2, arg3}) 46 | fake.downloadMutex.Unlock() 47 | if stub != nil { 48 | return stub(arg1, arg2, arg3) 49 | } 50 | if specificReturn { 51 | return ret.result1, ret.result2 52 | } 53 | return fakeReturns.result1, fakeReturns.result2 54 | } 55 | 56 | func (fake *FakeDownloader) DownloadCallCount() int { 57 | fake.downloadMutex.RLock() 58 | defer fake.downloadMutex.RUnlock() 59 | return len(fake.downloadArgsForCall) 60 | } 61 | 62 | func (fake *FakeDownloader) DownloadCalls(stub func([]pivnet.ProductFile, string, int) ([]string, error)) { 63 | fake.downloadMutex.Lock() 64 | defer fake.downloadMutex.Unlock() 65 | fake.DownloadStub = stub 66 | } 67 | 68 | func (fake *FakeDownloader) DownloadArgsForCall(i int) ([]pivnet.ProductFile, string, int) { 69 | fake.downloadMutex.RLock() 70 | defer fake.downloadMutex.RUnlock() 71 | argsForCall := fake.downloadArgsForCall[i] 72 | return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 73 | } 74 | 75 | func (fake *FakeDownloader) DownloadReturns(result1 []string, result2 error) { 76 | fake.downloadMutex.Lock() 77 | defer fake.downloadMutex.Unlock() 78 | fake.DownloadStub = nil 79 | fake.downloadReturns = struct { 80 | result1 []string 81 | result2 error 82 | }{result1, result2} 83 | } 84 | 85 | func (fake *FakeDownloader) DownloadReturnsOnCall(i int, result1 []string, result2 error) { 86 | fake.downloadMutex.Lock() 87 | defer fake.downloadMutex.Unlock() 88 | fake.DownloadStub = nil 89 | if fake.downloadReturnsOnCall == nil { 90 | fake.downloadReturnsOnCall = make(map[int]struct { 91 | result1 []string 92 | result2 error 93 | }) 94 | } 95 | fake.downloadReturnsOnCall[i] = struct { 96 | result1 []string 97 | result2 error 98 | }{result1, result2} 99 | } 100 | 101 | func (fake *FakeDownloader) Invocations() map[string][][]interface{} { 102 | fake.invocationsMutex.RLock() 103 | defer fake.invocationsMutex.RUnlock() 104 | fake.downloadMutex.RLock() 105 | defer fake.downloadMutex.RUnlock() 106 | copiedInvocations := map[string][][]interface{}{} 107 | for key, value := range fake.invocations { 108 | copiedInvocations[key] = value 109 | } 110 | return copiedInvocations 111 | } 112 | 113 | func (fake *FakeDownloader) recordInvocation(key string, args []interface{}) { 114 | fake.invocationsMutex.Lock() 115 | defer fake.invocationsMutex.Unlock() 116 | if fake.invocations == nil { 117 | fake.invocations = map[string][][]interface{}{} 118 | } 119 | if fake.invocations[key] == nil { 120 | fake.invocations[key] = [][]interface{}{} 121 | } 122 | fake.invocations[key] = append(fake.invocations[key], args) 123 | } 124 | -------------------------------------------------------------------------------- /in/infakes/fake_file_summer.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package infakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type FakeFileSummer struct { 9 | SumFileStub func(string) (string, error) 10 | sumFileMutex sync.RWMutex 11 | sumFileArgsForCall []struct { 12 | arg1 string 13 | } 14 | sumFileReturns struct { 15 | result1 string 16 | result2 error 17 | } 18 | sumFileReturnsOnCall map[int]struct { 19 | result1 string 20 | result2 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *FakeFileSummer) SumFile(arg1 string) (string, error) { 27 | fake.sumFileMutex.Lock() 28 | ret, specificReturn := fake.sumFileReturnsOnCall[len(fake.sumFileArgsForCall)] 29 | fake.sumFileArgsForCall = append(fake.sumFileArgsForCall, struct { 30 | arg1 string 31 | }{arg1}) 32 | stub := fake.SumFileStub 33 | fakeReturns := fake.sumFileReturns 34 | fake.recordInvocation("SumFile", []interface{}{arg1}) 35 | fake.sumFileMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1, ret.result2 41 | } 42 | return fakeReturns.result1, fakeReturns.result2 43 | } 44 | 45 | func (fake *FakeFileSummer) SumFileCallCount() int { 46 | fake.sumFileMutex.RLock() 47 | defer fake.sumFileMutex.RUnlock() 48 | return len(fake.sumFileArgsForCall) 49 | } 50 | 51 | func (fake *FakeFileSummer) SumFileCalls(stub func(string) (string, error)) { 52 | fake.sumFileMutex.Lock() 53 | defer fake.sumFileMutex.Unlock() 54 | fake.SumFileStub = stub 55 | } 56 | 57 | func (fake *FakeFileSummer) SumFileArgsForCall(i int) string { 58 | fake.sumFileMutex.RLock() 59 | defer fake.sumFileMutex.RUnlock() 60 | argsForCall := fake.sumFileArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *FakeFileSummer) SumFileReturns(result1 string, result2 error) { 65 | fake.sumFileMutex.Lock() 66 | defer fake.sumFileMutex.Unlock() 67 | fake.SumFileStub = nil 68 | fake.sumFileReturns = struct { 69 | result1 string 70 | result2 error 71 | }{result1, result2} 72 | } 73 | 74 | func (fake *FakeFileSummer) SumFileReturnsOnCall(i int, result1 string, result2 error) { 75 | fake.sumFileMutex.Lock() 76 | defer fake.sumFileMutex.Unlock() 77 | fake.SumFileStub = nil 78 | if fake.sumFileReturnsOnCall == nil { 79 | fake.sumFileReturnsOnCall = make(map[int]struct { 80 | result1 string 81 | result2 error 82 | }) 83 | } 84 | fake.sumFileReturnsOnCall[i] = struct { 85 | result1 string 86 | result2 error 87 | }{result1, result2} 88 | } 89 | 90 | func (fake *FakeFileSummer) Invocations() map[string][][]interface{} { 91 | fake.invocationsMutex.RLock() 92 | defer fake.invocationsMutex.RUnlock() 93 | fake.sumFileMutex.RLock() 94 | defer fake.sumFileMutex.RUnlock() 95 | copiedInvocations := map[string][][]interface{}{} 96 | for key, value := range fake.invocations { 97 | copiedInvocations[key] = value 98 | } 99 | return copiedInvocations 100 | } 101 | 102 | func (fake *FakeFileSummer) recordInvocation(key string, args []interface{}) { 103 | fake.invocationsMutex.Lock() 104 | defer fake.invocationsMutex.Unlock() 105 | if fake.invocations == nil { 106 | fake.invocations = map[string][][]interface{}{} 107 | } 108 | if fake.invocations[key] == nil { 109 | fake.invocations[key] = [][]interface{}{} 110 | } 111 | fake.invocations[key] = append(fake.invocations[key], args) 112 | } 113 | -------------------------------------------------------------------------------- /in/infakes/fake_filter.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package infakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type FakeFilter struct { 11 | ProductFileKeysByGlobsStub func([]pivnet.ProductFile, []string) ([]pivnet.ProductFile, error) 12 | productFileKeysByGlobsMutex sync.RWMutex 13 | productFileKeysByGlobsArgsForCall []struct { 14 | arg1 []pivnet.ProductFile 15 | arg2 []string 16 | } 17 | productFileKeysByGlobsReturns struct { 18 | result1 []pivnet.ProductFile 19 | result2 error 20 | } 21 | productFileKeysByGlobsReturnsOnCall map[int]struct { 22 | result1 []pivnet.ProductFile 23 | result2 error 24 | } 25 | invocations map[string][][]interface{} 26 | invocationsMutex sync.RWMutex 27 | } 28 | 29 | func (fake *FakeFilter) ProductFileKeysByGlobs(arg1 []pivnet.ProductFile, arg2 []string) ([]pivnet.ProductFile, error) { 30 | var arg1Copy []pivnet.ProductFile 31 | if arg1 != nil { 32 | arg1Copy = make([]pivnet.ProductFile, len(arg1)) 33 | copy(arg1Copy, arg1) 34 | } 35 | var arg2Copy []string 36 | if arg2 != nil { 37 | arg2Copy = make([]string, len(arg2)) 38 | copy(arg2Copy, arg2) 39 | } 40 | fake.productFileKeysByGlobsMutex.Lock() 41 | ret, specificReturn := fake.productFileKeysByGlobsReturnsOnCall[len(fake.productFileKeysByGlobsArgsForCall)] 42 | fake.productFileKeysByGlobsArgsForCall = append(fake.productFileKeysByGlobsArgsForCall, struct { 43 | arg1 []pivnet.ProductFile 44 | arg2 []string 45 | }{arg1Copy, arg2Copy}) 46 | stub := fake.ProductFileKeysByGlobsStub 47 | fakeReturns := fake.productFileKeysByGlobsReturns 48 | fake.recordInvocation("ProductFileKeysByGlobs", []interface{}{arg1Copy, arg2Copy}) 49 | fake.productFileKeysByGlobsMutex.Unlock() 50 | if stub != nil { 51 | return stub(arg1, arg2) 52 | } 53 | if specificReturn { 54 | return ret.result1, ret.result2 55 | } 56 | return fakeReturns.result1, fakeReturns.result2 57 | } 58 | 59 | func (fake *FakeFilter) ProductFileKeysByGlobsCallCount() int { 60 | fake.productFileKeysByGlobsMutex.RLock() 61 | defer fake.productFileKeysByGlobsMutex.RUnlock() 62 | return len(fake.productFileKeysByGlobsArgsForCall) 63 | } 64 | 65 | func (fake *FakeFilter) ProductFileKeysByGlobsCalls(stub func([]pivnet.ProductFile, []string) ([]pivnet.ProductFile, error)) { 66 | fake.productFileKeysByGlobsMutex.Lock() 67 | defer fake.productFileKeysByGlobsMutex.Unlock() 68 | fake.ProductFileKeysByGlobsStub = stub 69 | } 70 | 71 | func (fake *FakeFilter) ProductFileKeysByGlobsArgsForCall(i int) ([]pivnet.ProductFile, []string) { 72 | fake.productFileKeysByGlobsMutex.RLock() 73 | defer fake.productFileKeysByGlobsMutex.RUnlock() 74 | argsForCall := fake.productFileKeysByGlobsArgsForCall[i] 75 | return argsForCall.arg1, argsForCall.arg2 76 | } 77 | 78 | func (fake *FakeFilter) ProductFileKeysByGlobsReturns(result1 []pivnet.ProductFile, result2 error) { 79 | fake.productFileKeysByGlobsMutex.Lock() 80 | defer fake.productFileKeysByGlobsMutex.Unlock() 81 | fake.ProductFileKeysByGlobsStub = nil 82 | fake.productFileKeysByGlobsReturns = struct { 83 | result1 []pivnet.ProductFile 84 | result2 error 85 | }{result1, result2} 86 | } 87 | 88 | func (fake *FakeFilter) ProductFileKeysByGlobsReturnsOnCall(i int, result1 []pivnet.ProductFile, result2 error) { 89 | fake.productFileKeysByGlobsMutex.Lock() 90 | defer fake.productFileKeysByGlobsMutex.Unlock() 91 | fake.ProductFileKeysByGlobsStub = nil 92 | if fake.productFileKeysByGlobsReturnsOnCall == nil { 93 | fake.productFileKeysByGlobsReturnsOnCall = make(map[int]struct { 94 | result1 []pivnet.ProductFile 95 | result2 error 96 | }) 97 | } 98 | fake.productFileKeysByGlobsReturnsOnCall[i] = struct { 99 | result1 []pivnet.ProductFile 100 | result2 error 101 | }{result1, result2} 102 | } 103 | 104 | func (fake *FakeFilter) Invocations() map[string][][]interface{} { 105 | fake.invocationsMutex.RLock() 106 | defer fake.invocationsMutex.RUnlock() 107 | fake.productFileKeysByGlobsMutex.RLock() 108 | defer fake.productFileKeysByGlobsMutex.RUnlock() 109 | copiedInvocations := map[string][][]interface{}{} 110 | for key, value := range fake.invocations { 111 | copiedInvocations[key] = value 112 | } 113 | return copiedInvocations 114 | } 115 | 116 | func (fake *FakeFilter) recordInvocation(key string, args []interface{}) { 117 | fake.invocationsMutex.Lock() 118 | defer fake.invocationsMutex.Unlock() 119 | if fake.invocations == nil { 120 | fake.invocations = map[string][][]interface{}{} 121 | } 122 | if fake.invocations[key] == nil { 123 | fake.invocations[key] = [][]interface{}{} 124 | } 125 | fake.invocations[key] = append(fake.invocations[key], args) 126 | } 127 | -------------------------------------------------------------------------------- /in/package.go: -------------------------------------------------------------------------------- 1 | package in 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /metadata/metadata_suite_test.go: -------------------------------------------------------------------------------- 1 | package metadata_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestMetadata(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Metadata Suite") 13 | } 14 | -------------------------------------------------------------------------------- /out/out_suite_test.go: -------------------------------------------------------------------------------- 1 | package out_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestOut(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Out Suite") 13 | } 14 | -------------------------------------------------------------------------------- /out/outfakes/creator.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type Creator struct { 11 | CreateStub func() (pivnet.Release, error) 12 | createMutex sync.RWMutex 13 | createArgsForCall []struct { 14 | } 15 | createReturns struct { 16 | result1 pivnet.Release 17 | result2 error 18 | } 19 | createReturnsOnCall map[int]struct { 20 | result1 pivnet.Release 21 | result2 error 22 | } 23 | invocations map[string][][]interface{} 24 | invocationsMutex sync.RWMutex 25 | } 26 | 27 | func (fake *Creator) Create() (pivnet.Release, error) { 28 | fake.createMutex.Lock() 29 | ret, specificReturn := fake.createReturnsOnCall[len(fake.createArgsForCall)] 30 | fake.createArgsForCall = append(fake.createArgsForCall, struct { 31 | }{}) 32 | stub := fake.CreateStub 33 | fakeReturns := fake.createReturns 34 | fake.recordInvocation("Create", []interface{}{}) 35 | fake.createMutex.Unlock() 36 | if stub != nil { 37 | return stub() 38 | } 39 | if specificReturn { 40 | return ret.result1, ret.result2 41 | } 42 | return fakeReturns.result1, fakeReturns.result2 43 | } 44 | 45 | func (fake *Creator) CreateCallCount() int { 46 | fake.createMutex.RLock() 47 | defer fake.createMutex.RUnlock() 48 | return len(fake.createArgsForCall) 49 | } 50 | 51 | func (fake *Creator) CreateCalls(stub func() (pivnet.Release, error)) { 52 | fake.createMutex.Lock() 53 | defer fake.createMutex.Unlock() 54 | fake.CreateStub = stub 55 | } 56 | 57 | func (fake *Creator) CreateReturns(result1 pivnet.Release, result2 error) { 58 | fake.createMutex.Lock() 59 | defer fake.createMutex.Unlock() 60 | fake.CreateStub = nil 61 | fake.createReturns = struct { 62 | result1 pivnet.Release 63 | result2 error 64 | }{result1, result2} 65 | } 66 | 67 | func (fake *Creator) CreateReturnsOnCall(i int, result1 pivnet.Release, result2 error) { 68 | fake.createMutex.Lock() 69 | defer fake.createMutex.Unlock() 70 | fake.CreateStub = nil 71 | if fake.createReturnsOnCall == nil { 72 | fake.createReturnsOnCall = make(map[int]struct { 73 | result1 pivnet.Release 74 | result2 error 75 | }) 76 | } 77 | fake.createReturnsOnCall[i] = struct { 78 | result1 pivnet.Release 79 | result2 error 80 | }{result1, result2} 81 | } 82 | 83 | func (fake *Creator) Invocations() map[string][][]interface{} { 84 | fake.invocationsMutex.RLock() 85 | defer fake.invocationsMutex.RUnlock() 86 | fake.createMutex.RLock() 87 | defer fake.createMutex.RUnlock() 88 | copiedInvocations := map[string][][]interface{}{} 89 | for key, value := range fake.invocations { 90 | copiedInvocations[key] = value 91 | } 92 | return copiedInvocations 93 | } 94 | 95 | func (fake *Creator) recordInvocation(key string, args []interface{}) { 96 | fake.invocationsMutex.Lock() 97 | defer fake.invocationsMutex.Unlock() 98 | if fake.invocations == nil { 99 | fake.invocations = map[string][][]interface{}{} 100 | } 101 | if fake.invocations[key] == nil { 102 | fake.invocations[key] = [][]interface{}{} 103 | } 104 | fake.invocations[key] = append(fake.invocations[key], args) 105 | } 106 | -------------------------------------------------------------------------------- /out/outfakes/dependency_specifiers_creator.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type DependencySpecifiersCreator struct { 11 | CreateDependencySpecifiersStub func(pivnet.Release) error 12 | createDependencySpecifiersMutex sync.RWMutex 13 | createDependencySpecifiersArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | createDependencySpecifiersReturns struct { 17 | result1 error 18 | } 19 | createDependencySpecifiersReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *DependencySpecifiersCreator) CreateDependencySpecifiers(arg1 pivnet.Release) error { 27 | fake.createDependencySpecifiersMutex.Lock() 28 | ret, specificReturn := fake.createDependencySpecifiersReturnsOnCall[len(fake.createDependencySpecifiersArgsForCall)] 29 | fake.createDependencySpecifiersArgsForCall = append(fake.createDependencySpecifiersArgsForCall, struct { 30 | arg1 pivnet.Release 31 | }{arg1}) 32 | stub := fake.CreateDependencySpecifiersStub 33 | fakeReturns := fake.createDependencySpecifiersReturns 34 | fake.recordInvocation("CreateDependencySpecifiers", []interface{}{arg1}) 35 | fake.createDependencySpecifiersMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1 41 | } 42 | return fakeReturns.result1 43 | } 44 | 45 | func (fake *DependencySpecifiersCreator) CreateDependencySpecifiersCallCount() int { 46 | fake.createDependencySpecifiersMutex.RLock() 47 | defer fake.createDependencySpecifiersMutex.RUnlock() 48 | return len(fake.createDependencySpecifiersArgsForCall) 49 | } 50 | 51 | func (fake *DependencySpecifiersCreator) CreateDependencySpecifiersCalls(stub func(pivnet.Release) error) { 52 | fake.createDependencySpecifiersMutex.Lock() 53 | defer fake.createDependencySpecifiersMutex.Unlock() 54 | fake.CreateDependencySpecifiersStub = stub 55 | } 56 | 57 | func (fake *DependencySpecifiersCreator) CreateDependencySpecifiersArgsForCall(i int) pivnet.Release { 58 | fake.createDependencySpecifiersMutex.RLock() 59 | defer fake.createDependencySpecifiersMutex.RUnlock() 60 | argsForCall := fake.createDependencySpecifiersArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *DependencySpecifiersCreator) CreateDependencySpecifiersReturns(result1 error) { 65 | fake.createDependencySpecifiersMutex.Lock() 66 | defer fake.createDependencySpecifiersMutex.Unlock() 67 | fake.CreateDependencySpecifiersStub = nil 68 | fake.createDependencySpecifiersReturns = struct { 69 | result1 error 70 | }{result1} 71 | } 72 | 73 | func (fake *DependencySpecifiersCreator) CreateDependencySpecifiersReturnsOnCall(i int, result1 error) { 74 | fake.createDependencySpecifiersMutex.Lock() 75 | defer fake.createDependencySpecifiersMutex.Unlock() 76 | fake.CreateDependencySpecifiersStub = nil 77 | if fake.createDependencySpecifiersReturnsOnCall == nil { 78 | fake.createDependencySpecifiersReturnsOnCall = make(map[int]struct { 79 | result1 error 80 | }) 81 | } 82 | fake.createDependencySpecifiersReturnsOnCall[i] = struct { 83 | result1 error 84 | }{result1} 85 | } 86 | 87 | func (fake *DependencySpecifiersCreator) Invocations() map[string][][]interface{} { 88 | fake.invocationsMutex.RLock() 89 | defer fake.invocationsMutex.RUnlock() 90 | fake.createDependencySpecifiersMutex.RLock() 91 | defer fake.createDependencySpecifiersMutex.RUnlock() 92 | copiedInvocations := map[string][][]interface{}{} 93 | for key, value := range fake.invocations { 94 | copiedInvocations[key] = value 95 | } 96 | return copiedInvocations 97 | } 98 | 99 | func (fake *DependencySpecifiersCreator) recordInvocation(key string, args []interface{}) { 100 | fake.invocationsMutex.Lock() 101 | defer fake.invocationsMutex.Unlock() 102 | if fake.invocations == nil { 103 | fake.invocations = map[string][][]interface{}{} 104 | } 105 | if fake.invocations[key] == nil { 106 | fake.invocations[key] = [][]interface{}{} 107 | } 108 | fake.invocations[key] = append(fake.invocations[key], args) 109 | } 110 | -------------------------------------------------------------------------------- /out/outfakes/finalizer.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 8 | ) 9 | 10 | type Finalizer struct { 11 | FinalizeStub func(string, string) (concourse.OutResponse, error) 12 | finalizeMutex sync.RWMutex 13 | finalizeArgsForCall []struct { 14 | arg1 string 15 | arg2 string 16 | } 17 | finalizeReturns struct { 18 | result1 concourse.OutResponse 19 | result2 error 20 | } 21 | finalizeReturnsOnCall map[int]struct { 22 | result1 concourse.OutResponse 23 | result2 error 24 | } 25 | invocations map[string][][]interface{} 26 | invocationsMutex sync.RWMutex 27 | } 28 | 29 | func (fake *Finalizer) Finalize(arg1 string, arg2 string) (concourse.OutResponse, error) { 30 | fake.finalizeMutex.Lock() 31 | ret, specificReturn := fake.finalizeReturnsOnCall[len(fake.finalizeArgsForCall)] 32 | fake.finalizeArgsForCall = append(fake.finalizeArgsForCall, struct { 33 | arg1 string 34 | arg2 string 35 | }{arg1, arg2}) 36 | stub := fake.FinalizeStub 37 | fakeReturns := fake.finalizeReturns 38 | fake.recordInvocation("Finalize", []interface{}{arg1, arg2}) 39 | fake.finalizeMutex.Unlock() 40 | if stub != nil { 41 | return stub(arg1, arg2) 42 | } 43 | if specificReturn { 44 | return ret.result1, ret.result2 45 | } 46 | return fakeReturns.result1, fakeReturns.result2 47 | } 48 | 49 | func (fake *Finalizer) FinalizeCallCount() int { 50 | fake.finalizeMutex.RLock() 51 | defer fake.finalizeMutex.RUnlock() 52 | return len(fake.finalizeArgsForCall) 53 | } 54 | 55 | func (fake *Finalizer) FinalizeCalls(stub func(string, string) (concourse.OutResponse, error)) { 56 | fake.finalizeMutex.Lock() 57 | defer fake.finalizeMutex.Unlock() 58 | fake.FinalizeStub = stub 59 | } 60 | 61 | func (fake *Finalizer) FinalizeArgsForCall(i int) (string, string) { 62 | fake.finalizeMutex.RLock() 63 | defer fake.finalizeMutex.RUnlock() 64 | argsForCall := fake.finalizeArgsForCall[i] 65 | return argsForCall.arg1, argsForCall.arg2 66 | } 67 | 68 | func (fake *Finalizer) FinalizeReturns(result1 concourse.OutResponse, result2 error) { 69 | fake.finalizeMutex.Lock() 70 | defer fake.finalizeMutex.Unlock() 71 | fake.FinalizeStub = nil 72 | fake.finalizeReturns = struct { 73 | result1 concourse.OutResponse 74 | result2 error 75 | }{result1, result2} 76 | } 77 | 78 | func (fake *Finalizer) FinalizeReturnsOnCall(i int, result1 concourse.OutResponse, result2 error) { 79 | fake.finalizeMutex.Lock() 80 | defer fake.finalizeMutex.Unlock() 81 | fake.FinalizeStub = nil 82 | if fake.finalizeReturnsOnCall == nil { 83 | fake.finalizeReturnsOnCall = make(map[int]struct { 84 | result1 concourse.OutResponse 85 | result2 error 86 | }) 87 | } 88 | fake.finalizeReturnsOnCall[i] = struct { 89 | result1 concourse.OutResponse 90 | result2 error 91 | }{result1, result2} 92 | } 93 | 94 | func (fake *Finalizer) Invocations() map[string][][]interface{} { 95 | fake.invocationsMutex.RLock() 96 | defer fake.invocationsMutex.RUnlock() 97 | fake.finalizeMutex.RLock() 98 | defer fake.finalizeMutex.RUnlock() 99 | copiedInvocations := map[string][][]interface{}{} 100 | for key, value := range fake.invocations { 101 | copiedInvocations[key] = value 102 | } 103 | return copiedInvocations 104 | } 105 | 106 | func (fake *Finalizer) recordInvocation(key string, args []interface{}) { 107 | fake.invocationsMutex.Lock() 108 | defer fake.invocationsMutex.Unlock() 109 | if fake.invocations == nil { 110 | fake.invocations = map[string][][]interface{}{} 111 | } 112 | if fake.invocations[key] == nil { 113 | fake.invocations[key] = [][]interface{}{} 114 | } 115 | fake.invocations[key] = append(fake.invocations[key], args) 116 | } 117 | -------------------------------------------------------------------------------- /out/outfakes/finder.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type Finder struct { 11 | FindStub func(int) (pivnet.Release, error) 12 | findMutex sync.RWMutex 13 | findArgsForCall []struct { 14 | arg1 int 15 | } 16 | findReturns struct { 17 | result1 pivnet.Release 18 | result2 error 19 | } 20 | findReturnsOnCall map[int]struct { 21 | result1 pivnet.Release 22 | result2 error 23 | } 24 | invocations map[string][][]interface{} 25 | invocationsMutex sync.RWMutex 26 | } 27 | 28 | func (fake *Finder) Find(arg1 int) (pivnet.Release, error) { 29 | fake.findMutex.Lock() 30 | ret, specificReturn := fake.findReturnsOnCall[len(fake.findArgsForCall)] 31 | fake.findArgsForCall = append(fake.findArgsForCall, struct { 32 | arg1 int 33 | }{arg1}) 34 | stub := fake.FindStub 35 | fakeReturns := fake.findReturns 36 | fake.recordInvocation("Find", []interface{}{arg1}) 37 | fake.findMutex.Unlock() 38 | if stub != nil { 39 | return stub(arg1) 40 | } 41 | if specificReturn { 42 | return ret.result1, ret.result2 43 | } 44 | return fakeReturns.result1, fakeReturns.result2 45 | } 46 | 47 | func (fake *Finder) FindCallCount() int { 48 | fake.findMutex.RLock() 49 | defer fake.findMutex.RUnlock() 50 | return len(fake.findArgsForCall) 51 | } 52 | 53 | func (fake *Finder) FindCalls(stub func(int) (pivnet.Release, error)) { 54 | fake.findMutex.Lock() 55 | defer fake.findMutex.Unlock() 56 | fake.FindStub = stub 57 | } 58 | 59 | func (fake *Finder) FindArgsForCall(i int) int { 60 | fake.findMutex.RLock() 61 | defer fake.findMutex.RUnlock() 62 | argsForCall := fake.findArgsForCall[i] 63 | return argsForCall.arg1 64 | } 65 | 66 | func (fake *Finder) FindReturns(result1 pivnet.Release, result2 error) { 67 | fake.findMutex.Lock() 68 | defer fake.findMutex.Unlock() 69 | fake.FindStub = nil 70 | fake.findReturns = struct { 71 | result1 pivnet.Release 72 | result2 error 73 | }{result1, result2} 74 | } 75 | 76 | func (fake *Finder) FindReturnsOnCall(i int, result1 pivnet.Release, result2 error) { 77 | fake.findMutex.Lock() 78 | defer fake.findMutex.Unlock() 79 | fake.FindStub = nil 80 | if fake.findReturnsOnCall == nil { 81 | fake.findReturnsOnCall = make(map[int]struct { 82 | result1 pivnet.Release 83 | result2 error 84 | }) 85 | } 86 | fake.findReturnsOnCall[i] = struct { 87 | result1 pivnet.Release 88 | result2 error 89 | }{result1, result2} 90 | } 91 | 92 | func (fake *Finder) Invocations() map[string][][]interface{} { 93 | fake.invocationsMutex.RLock() 94 | defer fake.invocationsMutex.RUnlock() 95 | fake.findMutex.RLock() 96 | defer fake.findMutex.RUnlock() 97 | copiedInvocations := map[string][][]interface{}{} 98 | for key, value := range fake.invocations { 99 | copiedInvocations[key] = value 100 | } 101 | return copiedInvocations 102 | } 103 | 104 | func (fake *Finder) recordInvocation(key string, args []interface{}) { 105 | fake.invocationsMutex.Lock() 106 | defer fake.invocationsMutex.Unlock() 107 | if fake.invocations == nil { 108 | fake.invocations = map[string][][]interface{}{} 109 | } 110 | if fake.invocations[key] == nil { 111 | fake.invocations[key] = [][]interface{}{} 112 | } 113 | fake.invocations[key] = append(fake.invocations[key], args) 114 | } 115 | -------------------------------------------------------------------------------- /out/outfakes/globber.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type Globber struct { 9 | ExactGlobsStub func() ([]string, error) 10 | exactGlobsMutex sync.RWMutex 11 | exactGlobsArgsForCall []struct { 12 | } 13 | exactGlobsReturns struct { 14 | result1 []string 15 | result2 error 16 | } 17 | exactGlobsReturnsOnCall map[int]struct { 18 | result1 []string 19 | result2 error 20 | } 21 | invocations map[string][][]interface{} 22 | invocationsMutex sync.RWMutex 23 | } 24 | 25 | func (fake *Globber) ExactGlobs() ([]string, error) { 26 | fake.exactGlobsMutex.Lock() 27 | ret, specificReturn := fake.exactGlobsReturnsOnCall[len(fake.exactGlobsArgsForCall)] 28 | fake.exactGlobsArgsForCall = append(fake.exactGlobsArgsForCall, struct { 29 | }{}) 30 | stub := fake.ExactGlobsStub 31 | fakeReturns := fake.exactGlobsReturns 32 | fake.recordInvocation("ExactGlobs", []interface{}{}) 33 | fake.exactGlobsMutex.Unlock() 34 | if stub != nil { 35 | return stub() 36 | } 37 | if specificReturn { 38 | return ret.result1, ret.result2 39 | } 40 | return fakeReturns.result1, fakeReturns.result2 41 | } 42 | 43 | func (fake *Globber) ExactGlobsCallCount() int { 44 | fake.exactGlobsMutex.RLock() 45 | defer fake.exactGlobsMutex.RUnlock() 46 | return len(fake.exactGlobsArgsForCall) 47 | } 48 | 49 | func (fake *Globber) ExactGlobsCalls(stub func() ([]string, error)) { 50 | fake.exactGlobsMutex.Lock() 51 | defer fake.exactGlobsMutex.Unlock() 52 | fake.ExactGlobsStub = stub 53 | } 54 | 55 | func (fake *Globber) ExactGlobsReturns(result1 []string, result2 error) { 56 | fake.exactGlobsMutex.Lock() 57 | defer fake.exactGlobsMutex.Unlock() 58 | fake.ExactGlobsStub = nil 59 | fake.exactGlobsReturns = struct { 60 | result1 []string 61 | result2 error 62 | }{result1, result2} 63 | } 64 | 65 | func (fake *Globber) ExactGlobsReturnsOnCall(i int, result1 []string, result2 error) { 66 | fake.exactGlobsMutex.Lock() 67 | defer fake.exactGlobsMutex.Unlock() 68 | fake.ExactGlobsStub = nil 69 | if fake.exactGlobsReturnsOnCall == nil { 70 | fake.exactGlobsReturnsOnCall = make(map[int]struct { 71 | result1 []string 72 | result2 error 73 | }) 74 | } 75 | fake.exactGlobsReturnsOnCall[i] = struct { 76 | result1 []string 77 | result2 error 78 | }{result1, result2} 79 | } 80 | 81 | func (fake *Globber) Invocations() map[string][][]interface{} { 82 | fake.invocationsMutex.RLock() 83 | defer fake.invocationsMutex.RUnlock() 84 | fake.exactGlobsMutex.RLock() 85 | defer fake.exactGlobsMutex.RUnlock() 86 | copiedInvocations := map[string][][]interface{}{} 87 | for key, value := range fake.invocations { 88 | copiedInvocations[key] = value 89 | } 90 | return copiedInvocations 91 | } 92 | 93 | func (fake *Globber) recordInvocation(key string, args []interface{}) { 94 | fake.invocationsMutex.Lock() 95 | defer fake.invocationsMutex.Unlock() 96 | if fake.invocations == nil { 97 | fake.invocations = map[string][][]interface{}{} 98 | } 99 | if fake.invocations[key] == nil { 100 | fake.invocations[key] = [][]interface{}{} 101 | } 102 | fake.invocations[key] = append(fake.invocations[key], args) 103 | } 104 | -------------------------------------------------------------------------------- /out/outfakes/release_artifact_references_adder.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type ReleaseArtifactReferencesAdder struct { 11 | AddReleaseArtifactReferencesStub func(pivnet.Release) error 12 | addReleaseArtifactReferencesMutex sync.RWMutex 13 | addReleaseArtifactReferencesArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | addReleaseArtifactReferencesReturns struct { 17 | result1 error 18 | } 19 | addReleaseArtifactReferencesReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *ReleaseArtifactReferencesAdder) AddReleaseArtifactReferences(arg1 pivnet.Release) error { 27 | fake.addReleaseArtifactReferencesMutex.Lock() 28 | ret, specificReturn := fake.addReleaseArtifactReferencesReturnsOnCall[len(fake.addReleaseArtifactReferencesArgsForCall)] 29 | fake.addReleaseArtifactReferencesArgsForCall = append(fake.addReleaseArtifactReferencesArgsForCall, struct { 30 | arg1 pivnet.Release 31 | }{arg1}) 32 | stub := fake.AddReleaseArtifactReferencesStub 33 | fakeReturns := fake.addReleaseArtifactReferencesReturns 34 | fake.recordInvocation("AddReleaseArtifactReferences", []interface{}{arg1}) 35 | fake.addReleaseArtifactReferencesMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1 41 | } 42 | return fakeReturns.result1 43 | } 44 | 45 | func (fake *ReleaseArtifactReferencesAdder) AddReleaseArtifactReferencesCallCount() int { 46 | fake.addReleaseArtifactReferencesMutex.RLock() 47 | defer fake.addReleaseArtifactReferencesMutex.RUnlock() 48 | return len(fake.addReleaseArtifactReferencesArgsForCall) 49 | } 50 | 51 | func (fake *ReleaseArtifactReferencesAdder) AddReleaseArtifactReferencesCalls(stub func(pivnet.Release) error) { 52 | fake.addReleaseArtifactReferencesMutex.Lock() 53 | defer fake.addReleaseArtifactReferencesMutex.Unlock() 54 | fake.AddReleaseArtifactReferencesStub = stub 55 | } 56 | 57 | func (fake *ReleaseArtifactReferencesAdder) AddReleaseArtifactReferencesArgsForCall(i int) pivnet.Release { 58 | fake.addReleaseArtifactReferencesMutex.RLock() 59 | defer fake.addReleaseArtifactReferencesMutex.RUnlock() 60 | argsForCall := fake.addReleaseArtifactReferencesArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *ReleaseArtifactReferencesAdder) AddReleaseArtifactReferencesReturns(result1 error) { 65 | fake.addReleaseArtifactReferencesMutex.Lock() 66 | defer fake.addReleaseArtifactReferencesMutex.Unlock() 67 | fake.AddReleaseArtifactReferencesStub = nil 68 | fake.addReleaseArtifactReferencesReturns = struct { 69 | result1 error 70 | }{result1} 71 | } 72 | 73 | func (fake *ReleaseArtifactReferencesAdder) AddReleaseArtifactReferencesReturnsOnCall(i int, result1 error) { 74 | fake.addReleaseArtifactReferencesMutex.Lock() 75 | defer fake.addReleaseArtifactReferencesMutex.Unlock() 76 | fake.AddReleaseArtifactReferencesStub = nil 77 | if fake.addReleaseArtifactReferencesReturnsOnCall == nil { 78 | fake.addReleaseArtifactReferencesReturnsOnCall = make(map[int]struct { 79 | result1 error 80 | }) 81 | } 82 | fake.addReleaseArtifactReferencesReturnsOnCall[i] = struct { 83 | result1 error 84 | }{result1} 85 | } 86 | 87 | func (fake *ReleaseArtifactReferencesAdder) Invocations() map[string][][]interface{} { 88 | fake.invocationsMutex.RLock() 89 | defer fake.invocationsMutex.RUnlock() 90 | fake.addReleaseArtifactReferencesMutex.RLock() 91 | defer fake.addReleaseArtifactReferencesMutex.RUnlock() 92 | copiedInvocations := map[string][][]interface{}{} 93 | for key, value := range fake.invocations { 94 | copiedInvocations[key] = value 95 | } 96 | return copiedInvocations 97 | } 98 | 99 | func (fake *ReleaseArtifactReferencesAdder) recordInvocation(key string, args []interface{}) { 100 | fake.invocationsMutex.Lock() 101 | defer fake.invocationsMutex.Unlock() 102 | if fake.invocations == nil { 103 | fake.invocations = map[string][][]interface{}{} 104 | } 105 | if fake.invocations[key] == nil { 106 | fake.invocations[key] = [][]interface{}{} 107 | } 108 | fake.invocations[key] = append(fake.invocations[key], args) 109 | } 110 | -------------------------------------------------------------------------------- /out/outfakes/release_dependencies_adder.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type ReleaseDependenciesAdder struct { 11 | AddReleaseDependenciesStub func(pivnet.Release) error 12 | addReleaseDependenciesMutex sync.RWMutex 13 | addReleaseDependenciesArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | addReleaseDependenciesReturns struct { 17 | result1 error 18 | } 19 | addReleaseDependenciesReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *ReleaseDependenciesAdder) AddReleaseDependencies(arg1 pivnet.Release) error { 27 | fake.addReleaseDependenciesMutex.Lock() 28 | ret, specificReturn := fake.addReleaseDependenciesReturnsOnCall[len(fake.addReleaseDependenciesArgsForCall)] 29 | fake.addReleaseDependenciesArgsForCall = append(fake.addReleaseDependenciesArgsForCall, struct { 30 | arg1 pivnet.Release 31 | }{arg1}) 32 | stub := fake.AddReleaseDependenciesStub 33 | fakeReturns := fake.addReleaseDependenciesReturns 34 | fake.recordInvocation("AddReleaseDependencies", []interface{}{arg1}) 35 | fake.addReleaseDependenciesMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1 41 | } 42 | return fakeReturns.result1 43 | } 44 | 45 | func (fake *ReleaseDependenciesAdder) AddReleaseDependenciesCallCount() int { 46 | fake.addReleaseDependenciesMutex.RLock() 47 | defer fake.addReleaseDependenciesMutex.RUnlock() 48 | return len(fake.addReleaseDependenciesArgsForCall) 49 | } 50 | 51 | func (fake *ReleaseDependenciesAdder) AddReleaseDependenciesCalls(stub func(pivnet.Release) error) { 52 | fake.addReleaseDependenciesMutex.Lock() 53 | defer fake.addReleaseDependenciesMutex.Unlock() 54 | fake.AddReleaseDependenciesStub = stub 55 | } 56 | 57 | func (fake *ReleaseDependenciesAdder) AddReleaseDependenciesArgsForCall(i int) pivnet.Release { 58 | fake.addReleaseDependenciesMutex.RLock() 59 | defer fake.addReleaseDependenciesMutex.RUnlock() 60 | argsForCall := fake.addReleaseDependenciesArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *ReleaseDependenciesAdder) AddReleaseDependenciesReturns(result1 error) { 65 | fake.addReleaseDependenciesMutex.Lock() 66 | defer fake.addReleaseDependenciesMutex.Unlock() 67 | fake.AddReleaseDependenciesStub = nil 68 | fake.addReleaseDependenciesReturns = struct { 69 | result1 error 70 | }{result1} 71 | } 72 | 73 | func (fake *ReleaseDependenciesAdder) AddReleaseDependenciesReturnsOnCall(i int, result1 error) { 74 | fake.addReleaseDependenciesMutex.Lock() 75 | defer fake.addReleaseDependenciesMutex.Unlock() 76 | fake.AddReleaseDependenciesStub = nil 77 | if fake.addReleaseDependenciesReturnsOnCall == nil { 78 | fake.addReleaseDependenciesReturnsOnCall = make(map[int]struct { 79 | result1 error 80 | }) 81 | } 82 | fake.addReleaseDependenciesReturnsOnCall[i] = struct { 83 | result1 error 84 | }{result1} 85 | } 86 | 87 | func (fake *ReleaseDependenciesAdder) Invocations() map[string][][]interface{} { 88 | fake.invocationsMutex.RLock() 89 | defer fake.invocationsMutex.RUnlock() 90 | fake.addReleaseDependenciesMutex.RLock() 91 | defer fake.addReleaseDependenciesMutex.RUnlock() 92 | copiedInvocations := map[string][][]interface{}{} 93 | for key, value := range fake.invocations { 94 | copiedInvocations[key] = value 95 | } 96 | return copiedInvocations 97 | } 98 | 99 | func (fake *ReleaseDependenciesAdder) recordInvocation(key string, args []interface{}) { 100 | fake.invocationsMutex.Lock() 101 | defer fake.invocationsMutex.Unlock() 102 | if fake.invocations == nil { 103 | fake.invocations = map[string][][]interface{}{} 104 | } 105 | if fake.invocations[key] == nil { 106 | fake.invocations[key] = [][]interface{}{} 107 | } 108 | fake.invocations[key] = append(fake.invocations[key], args) 109 | } 110 | -------------------------------------------------------------------------------- /out/outfakes/release_file_groups_adder.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type ReleaseFileGroupsAdder struct { 11 | AddReleaseFileGroupsStub func(pivnet.Release) error 12 | addReleaseFileGroupsMutex sync.RWMutex 13 | addReleaseFileGroupsArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | addReleaseFileGroupsReturns struct { 17 | result1 error 18 | } 19 | addReleaseFileGroupsReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *ReleaseFileGroupsAdder) AddReleaseFileGroups(arg1 pivnet.Release) error { 27 | fake.addReleaseFileGroupsMutex.Lock() 28 | ret, specificReturn := fake.addReleaseFileGroupsReturnsOnCall[len(fake.addReleaseFileGroupsArgsForCall)] 29 | fake.addReleaseFileGroupsArgsForCall = append(fake.addReleaseFileGroupsArgsForCall, struct { 30 | arg1 pivnet.Release 31 | }{arg1}) 32 | stub := fake.AddReleaseFileGroupsStub 33 | fakeReturns := fake.addReleaseFileGroupsReturns 34 | fake.recordInvocation("AddReleaseFileGroups", []interface{}{arg1}) 35 | fake.addReleaseFileGroupsMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1 41 | } 42 | return fakeReturns.result1 43 | } 44 | 45 | func (fake *ReleaseFileGroupsAdder) AddReleaseFileGroupsCallCount() int { 46 | fake.addReleaseFileGroupsMutex.RLock() 47 | defer fake.addReleaseFileGroupsMutex.RUnlock() 48 | return len(fake.addReleaseFileGroupsArgsForCall) 49 | } 50 | 51 | func (fake *ReleaseFileGroupsAdder) AddReleaseFileGroupsCalls(stub func(pivnet.Release) error) { 52 | fake.addReleaseFileGroupsMutex.Lock() 53 | defer fake.addReleaseFileGroupsMutex.Unlock() 54 | fake.AddReleaseFileGroupsStub = stub 55 | } 56 | 57 | func (fake *ReleaseFileGroupsAdder) AddReleaseFileGroupsArgsForCall(i int) pivnet.Release { 58 | fake.addReleaseFileGroupsMutex.RLock() 59 | defer fake.addReleaseFileGroupsMutex.RUnlock() 60 | argsForCall := fake.addReleaseFileGroupsArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *ReleaseFileGroupsAdder) AddReleaseFileGroupsReturns(result1 error) { 65 | fake.addReleaseFileGroupsMutex.Lock() 66 | defer fake.addReleaseFileGroupsMutex.Unlock() 67 | fake.AddReleaseFileGroupsStub = nil 68 | fake.addReleaseFileGroupsReturns = struct { 69 | result1 error 70 | }{result1} 71 | } 72 | 73 | func (fake *ReleaseFileGroupsAdder) AddReleaseFileGroupsReturnsOnCall(i int, result1 error) { 74 | fake.addReleaseFileGroupsMutex.Lock() 75 | defer fake.addReleaseFileGroupsMutex.Unlock() 76 | fake.AddReleaseFileGroupsStub = nil 77 | if fake.addReleaseFileGroupsReturnsOnCall == nil { 78 | fake.addReleaseFileGroupsReturnsOnCall = make(map[int]struct { 79 | result1 error 80 | }) 81 | } 82 | fake.addReleaseFileGroupsReturnsOnCall[i] = struct { 83 | result1 error 84 | }{result1} 85 | } 86 | 87 | func (fake *ReleaseFileGroupsAdder) Invocations() map[string][][]interface{} { 88 | fake.invocationsMutex.RLock() 89 | defer fake.invocationsMutex.RUnlock() 90 | fake.addReleaseFileGroupsMutex.RLock() 91 | defer fake.addReleaseFileGroupsMutex.RUnlock() 92 | copiedInvocations := map[string][][]interface{}{} 93 | for key, value := range fake.invocations { 94 | copiedInvocations[key] = value 95 | } 96 | return copiedInvocations 97 | } 98 | 99 | func (fake *ReleaseFileGroupsAdder) recordInvocation(key string, args []interface{}) { 100 | fake.invocationsMutex.Lock() 101 | defer fake.invocationsMutex.Unlock() 102 | if fake.invocations == nil { 103 | fake.invocations = map[string][][]interface{}{} 104 | } 105 | if fake.invocations[key] == nil { 106 | fake.invocations[key] = [][]interface{}{} 107 | } 108 | fake.invocations[key] = append(fake.invocations[key], args) 109 | } 110 | -------------------------------------------------------------------------------- /out/outfakes/release_upgrade_paths_adder.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type ReleaseUpgradePathsAdder struct { 11 | AddReleaseUpgradePathsStub func(pivnet.Release) error 12 | addReleaseUpgradePathsMutex sync.RWMutex 13 | addReleaseUpgradePathsArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | addReleaseUpgradePathsReturns struct { 17 | result1 error 18 | } 19 | addReleaseUpgradePathsReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *ReleaseUpgradePathsAdder) AddReleaseUpgradePaths(arg1 pivnet.Release) error { 27 | fake.addReleaseUpgradePathsMutex.Lock() 28 | ret, specificReturn := fake.addReleaseUpgradePathsReturnsOnCall[len(fake.addReleaseUpgradePathsArgsForCall)] 29 | fake.addReleaseUpgradePathsArgsForCall = append(fake.addReleaseUpgradePathsArgsForCall, struct { 30 | arg1 pivnet.Release 31 | }{arg1}) 32 | stub := fake.AddReleaseUpgradePathsStub 33 | fakeReturns := fake.addReleaseUpgradePathsReturns 34 | fake.recordInvocation("AddReleaseUpgradePaths", []interface{}{arg1}) 35 | fake.addReleaseUpgradePathsMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1 41 | } 42 | return fakeReturns.result1 43 | } 44 | 45 | func (fake *ReleaseUpgradePathsAdder) AddReleaseUpgradePathsCallCount() int { 46 | fake.addReleaseUpgradePathsMutex.RLock() 47 | defer fake.addReleaseUpgradePathsMutex.RUnlock() 48 | return len(fake.addReleaseUpgradePathsArgsForCall) 49 | } 50 | 51 | func (fake *ReleaseUpgradePathsAdder) AddReleaseUpgradePathsCalls(stub func(pivnet.Release) error) { 52 | fake.addReleaseUpgradePathsMutex.Lock() 53 | defer fake.addReleaseUpgradePathsMutex.Unlock() 54 | fake.AddReleaseUpgradePathsStub = stub 55 | } 56 | 57 | func (fake *ReleaseUpgradePathsAdder) AddReleaseUpgradePathsArgsForCall(i int) pivnet.Release { 58 | fake.addReleaseUpgradePathsMutex.RLock() 59 | defer fake.addReleaseUpgradePathsMutex.RUnlock() 60 | argsForCall := fake.addReleaseUpgradePathsArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *ReleaseUpgradePathsAdder) AddReleaseUpgradePathsReturns(result1 error) { 65 | fake.addReleaseUpgradePathsMutex.Lock() 66 | defer fake.addReleaseUpgradePathsMutex.Unlock() 67 | fake.AddReleaseUpgradePathsStub = nil 68 | fake.addReleaseUpgradePathsReturns = struct { 69 | result1 error 70 | }{result1} 71 | } 72 | 73 | func (fake *ReleaseUpgradePathsAdder) AddReleaseUpgradePathsReturnsOnCall(i int, result1 error) { 74 | fake.addReleaseUpgradePathsMutex.Lock() 75 | defer fake.addReleaseUpgradePathsMutex.Unlock() 76 | fake.AddReleaseUpgradePathsStub = nil 77 | if fake.addReleaseUpgradePathsReturnsOnCall == nil { 78 | fake.addReleaseUpgradePathsReturnsOnCall = make(map[int]struct { 79 | result1 error 80 | }) 81 | } 82 | fake.addReleaseUpgradePathsReturnsOnCall[i] = struct { 83 | result1 error 84 | }{result1} 85 | } 86 | 87 | func (fake *ReleaseUpgradePathsAdder) Invocations() map[string][][]interface{} { 88 | fake.invocationsMutex.RLock() 89 | defer fake.invocationsMutex.RUnlock() 90 | fake.addReleaseUpgradePathsMutex.RLock() 91 | defer fake.addReleaseUpgradePathsMutex.RUnlock() 92 | copiedInvocations := map[string][][]interface{}{} 93 | for key, value := range fake.invocations { 94 | copiedInvocations[key] = value 95 | } 96 | return copiedInvocations 97 | } 98 | 99 | func (fake *ReleaseUpgradePathsAdder) recordInvocation(key string, args []interface{}) { 100 | fake.invocationsMutex.Lock() 101 | defer fake.invocationsMutex.Unlock() 102 | if fake.invocations == nil { 103 | fake.invocations = map[string][][]interface{}{} 104 | } 105 | if fake.invocations[key] == nil { 106 | fake.invocations[key] = [][]interface{}{} 107 | } 108 | fake.invocations[key] = append(fake.invocations[key], args) 109 | } 110 | -------------------------------------------------------------------------------- /out/outfakes/upgrade_path_specifiers_creator.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type UpgradePathSpecifiersCreator struct { 11 | CreateUpgradePathSpecifiersStub func(pivnet.Release) error 12 | createUpgradePathSpecifiersMutex sync.RWMutex 13 | createUpgradePathSpecifiersArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | createUpgradePathSpecifiersReturns struct { 17 | result1 error 18 | } 19 | createUpgradePathSpecifiersReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiers(arg1 pivnet.Release) error { 27 | fake.createUpgradePathSpecifiersMutex.Lock() 28 | ret, specificReturn := fake.createUpgradePathSpecifiersReturnsOnCall[len(fake.createUpgradePathSpecifiersArgsForCall)] 29 | fake.createUpgradePathSpecifiersArgsForCall = append(fake.createUpgradePathSpecifiersArgsForCall, struct { 30 | arg1 pivnet.Release 31 | }{arg1}) 32 | stub := fake.CreateUpgradePathSpecifiersStub 33 | fakeReturns := fake.createUpgradePathSpecifiersReturns 34 | fake.recordInvocation("CreateUpgradePathSpecifiers", []interface{}{arg1}) 35 | fake.createUpgradePathSpecifiersMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1 41 | } 42 | return fakeReturns.result1 43 | } 44 | 45 | func (fake *UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiersCallCount() int { 46 | fake.createUpgradePathSpecifiersMutex.RLock() 47 | defer fake.createUpgradePathSpecifiersMutex.RUnlock() 48 | return len(fake.createUpgradePathSpecifiersArgsForCall) 49 | } 50 | 51 | func (fake *UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiersCalls(stub func(pivnet.Release) error) { 52 | fake.createUpgradePathSpecifiersMutex.Lock() 53 | defer fake.createUpgradePathSpecifiersMutex.Unlock() 54 | fake.CreateUpgradePathSpecifiersStub = stub 55 | } 56 | 57 | func (fake *UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiersArgsForCall(i int) pivnet.Release { 58 | fake.createUpgradePathSpecifiersMutex.RLock() 59 | defer fake.createUpgradePathSpecifiersMutex.RUnlock() 60 | argsForCall := fake.createUpgradePathSpecifiersArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiersReturns(result1 error) { 65 | fake.createUpgradePathSpecifiersMutex.Lock() 66 | defer fake.createUpgradePathSpecifiersMutex.Unlock() 67 | fake.CreateUpgradePathSpecifiersStub = nil 68 | fake.createUpgradePathSpecifiersReturns = struct { 69 | result1 error 70 | }{result1} 71 | } 72 | 73 | func (fake *UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiersReturnsOnCall(i int, result1 error) { 74 | fake.createUpgradePathSpecifiersMutex.Lock() 75 | defer fake.createUpgradePathSpecifiersMutex.Unlock() 76 | fake.CreateUpgradePathSpecifiersStub = nil 77 | if fake.createUpgradePathSpecifiersReturnsOnCall == nil { 78 | fake.createUpgradePathSpecifiersReturnsOnCall = make(map[int]struct { 79 | result1 error 80 | }) 81 | } 82 | fake.createUpgradePathSpecifiersReturnsOnCall[i] = struct { 83 | result1 error 84 | }{result1} 85 | } 86 | 87 | func (fake *UpgradePathSpecifiersCreator) Invocations() map[string][][]interface{} { 88 | fake.invocationsMutex.RLock() 89 | defer fake.invocationsMutex.RUnlock() 90 | fake.createUpgradePathSpecifiersMutex.RLock() 91 | defer fake.createUpgradePathSpecifiersMutex.RUnlock() 92 | copiedInvocations := map[string][][]interface{}{} 93 | for key, value := range fake.invocations { 94 | copiedInvocations[key] = value 95 | } 96 | return copiedInvocations 97 | } 98 | 99 | func (fake *UpgradePathSpecifiersCreator) recordInvocation(key string, args []interface{}) { 100 | fake.invocationsMutex.Lock() 101 | defer fake.invocationsMutex.Unlock() 102 | if fake.invocations == nil { 103 | fake.invocations = map[string][][]interface{}{} 104 | } 105 | if fake.invocations[key] == nil { 106 | fake.invocations[key] = [][]interface{}{} 107 | } 108 | fake.invocations[key] = append(fake.invocations[key], args) 109 | } 110 | -------------------------------------------------------------------------------- /out/outfakes/uploader.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type Uploader struct { 11 | UploadStub func(pivnet.Release, []string) error 12 | uploadMutex sync.RWMutex 13 | uploadArgsForCall []struct { 14 | arg1 pivnet.Release 15 | arg2 []string 16 | } 17 | uploadReturns struct { 18 | result1 error 19 | } 20 | uploadReturnsOnCall map[int]struct { 21 | result1 error 22 | } 23 | invocations map[string][][]interface{} 24 | invocationsMutex sync.RWMutex 25 | } 26 | 27 | func (fake *Uploader) Upload(arg1 pivnet.Release, arg2 []string) error { 28 | var arg2Copy []string 29 | if arg2 != nil { 30 | arg2Copy = make([]string, len(arg2)) 31 | copy(arg2Copy, arg2) 32 | } 33 | fake.uploadMutex.Lock() 34 | ret, specificReturn := fake.uploadReturnsOnCall[len(fake.uploadArgsForCall)] 35 | fake.uploadArgsForCall = append(fake.uploadArgsForCall, struct { 36 | arg1 pivnet.Release 37 | arg2 []string 38 | }{arg1, arg2Copy}) 39 | stub := fake.UploadStub 40 | fakeReturns := fake.uploadReturns 41 | fake.recordInvocation("Upload", []interface{}{arg1, arg2Copy}) 42 | fake.uploadMutex.Unlock() 43 | if stub != nil { 44 | return stub(arg1, arg2) 45 | } 46 | if specificReturn { 47 | return ret.result1 48 | } 49 | return fakeReturns.result1 50 | } 51 | 52 | func (fake *Uploader) UploadCallCount() int { 53 | fake.uploadMutex.RLock() 54 | defer fake.uploadMutex.RUnlock() 55 | return len(fake.uploadArgsForCall) 56 | } 57 | 58 | func (fake *Uploader) UploadCalls(stub func(pivnet.Release, []string) error) { 59 | fake.uploadMutex.Lock() 60 | defer fake.uploadMutex.Unlock() 61 | fake.UploadStub = stub 62 | } 63 | 64 | func (fake *Uploader) UploadArgsForCall(i int) (pivnet.Release, []string) { 65 | fake.uploadMutex.RLock() 66 | defer fake.uploadMutex.RUnlock() 67 | argsForCall := fake.uploadArgsForCall[i] 68 | return argsForCall.arg1, argsForCall.arg2 69 | } 70 | 71 | func (fake *Uploader) UploadReturns(result1 error) { 72 | fake.uploadMutex.Lock() 73 | defer fake.uploadMutex.Unlock() 74 | fake.UploadStub = nil 75 | fake.uploadReturns = struct { 76 | result1 error 77 | }{result1} 78 | } 79 | 80 | func (fake *Uploader) UploadReturnsOnCall(i int, result1 error) { 81 | fake.uploadMutex.Lock() 82 | defer fake.uploadMutex.Unlock() 83 | fake.UploadStub = nil 84 | if fake.uploadReturnsOnCall == nil { 85 | fake.uploadReturnsOnCall = make(map[int]struct { 86 | result1 error 87 | }) 88 | } 89 | fake.uploadReturnsOnCall[i] = struct { 90 | result1 error 91 | }{result1} 92 | } 93 | 94 | func (fake *Uploader) Invocations() map[string][][]interface{} { 95 | fake.invocationsMutex.RLock() 96 | defer fake.invocationsMutex.RUnlock() 97 | fake.uploadMutex.RLock() 98 | defer fake.uploadMutex.RUnlock() 99 | copiedInvocations := map[string][][]interface{}{} 100 | for key, value := range fake.invocations { 101 | copiedInvocations[key] = value 102 | } 103 | return copiedInvocations 104 | } 105 | 106 | func (fake *Uploader) recordInvocation(key string, args []interface{}) { 107 | fake.invocationsMutex.Lock() 108 | defer fake.invocationsMutex.Unlock() 109 | if fake.invocations == nil { 110 | fake.invocations = map[string][][]interface{}{} 111 | } 112 | if fake.invocations[key] == nil { 113 | fake.invocations[key] = [][]interface{}{} 114 | } 115 | fake.invocations[key] = append(fake.invocations[key], args) 116 | } 117 | -------------------------------------------------------------------------------- /out/outfakes/user_groups_updater.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type UserGroupsUpdater struct { 11 | UpdateUserGroupsStub func(pivnet.Release) (pivnet.Release, error) 12 | updateUserGroupsMutex sync.RWMutex 13 | updateUserGroupsArgsForCall []struct { 14 | arg1 pivnet.Release 15 | } 16 | updateUserGroupsReturns struct { 17 | result1 pivnet.Release 18 | result2 error 19 | } 20 | updateUserGroupsReturnsOnCall map[int]struct { 21 | result1 pivnet.Release 22 | result2 error 23 | } 24 | invocations map[string][][]interface{} 25 | invocationsMutex sync.RWMutex 26 | } 27 | 28 | func (fake *UserGroupsUpdater) UpdateUserGroups(arg1 pivnet.Release) (pivnet.Release, error) { 29 | fake.updateUserGroupsMutex.Lock() 30 | ret, specificReturn := fake.updateUserGroupsReturnsOnCall[len(fake.updateUserGroupsArgsForCall)] 31 | fake.updateUserGroupsArgsForCall = append(fake.updateUserGroupsArgsForCall, struct { 32 | arg1 pivnet.Release 33 | }{arg1}) 34 | stub := fake.UpdateUserGroupsStub 35 | fakeReturns := fake.updateUserGroupsReturns 36 | fake.recordInvocation("UpdateUserGroups", []interface{}{arg1}) 37 | fake.updateUserGroupsMutex.Unlock() 38 | if stub != nil { 39 | return stub(arg1) 40 | } 41 | if specificReturn { 42 | return ret.result1, ret.result2 43 | } 44 | return fakeReturns.result1, fakeReturns.result2 45 | } 46 | 47 | func (fake *UserGroupsUpdater) UpdateUserGroupsCallCount() int { 48 | fake.updateUserGroupsMutex.RLock() 49 | defer fake.updateUserGroupsMutex.RUnlock() 50 | return len(fake.updateUserGroupsArgsForCall) 51 | } 52 | 53 | func (fake *UserGroupsUpdater) UpdateUserGroupsCalls(stub func(pivnet.Release) (pivnet.Release, error)) { 54 | fake.updateUserGroupsMutex.Lock() 55 | defer fake.updateUserGroupsMutex.Unlock() 56 | fake.UpdateUserGroupsStub = stub 57 | } 58 | 59 | func (fake *UserGroupsUpdater) UpdateUserGroupsArgsForCall(i int) pivnet.Release { 60 | fake.updateUserGroupsMutex.RLock() 61 | defer fake.updateUserGroupsMutex.RUnlock() 62 | argsForCall := fake.updateUserGroupsArgsForCall[i] 63 | return argsForCall.arg1 64 | } 65 | 66 | func (fake *UserGroupsUpdater) UpdateUserGroupsReturns(result1 pivnet.Release, result2 error) { 67 | fake.updateUserGroupsMutex.Lock() 68 | defer fake.updateUserGroupsMutex.Unlock() 69 | fake.UpdateUserGroupsStub = nil 70 | fake.updateUserGroupsReturns = struct { 71 | result1 pivnet.Release 72 | result2 error 73 | }{result1, result2} 74 | } 75 | 76 | func (fake *UserGroupsUpdater) UpdateUserGroupsReturnsOnCall(i int, result1 pivnet.Release, result2 error) { 77 | fake.updateUserGroupsMutex.Lock() 78 | defer fake.updateUserGroupsMutex.Unlock() 79 | fake.UpdateUserGroupsStub = nil 80 | if fake.updateUserGroupsReturnsOnCall == nil { 81 | fake.updateUserGroupsReturnsOnCall = make(map[int]struct { 82 | result1 pivnet.Release 83 | result2 error 84 | }) 85 | } 86 | fake.updateUserGroupsReturnsOnCall[i] = struct { 87 | result1 pivnet.Release 88 | result2 error 89 | }{result1, result2} 90 | } 91 | 92 | func (fake *UserGroupsUpdater) Invocations() map[string][][]interface{} { 93 | fake.invocationsMutex.RLock() 94 | defer fake.invocationsMutex.RUnlock() 95 | fake.updateUserGroupsMutex.RLock() 96 | defer fake.updateUserGroupsMutex.RUnlock() 97 | copiedInvocations := map[string][][]interface{}{} 98 | for key, value := range fake.invocations { 99 | copiedInvocations[key] = value 100 | } 101 | return copiedInvocations 102 | } 103 | 104 | func (fake *UserGroupsUpdater) recordInvocation(key string, args []interface{}) { 105 | fake.invocationsMutex.Lock() 106 | defer fake.invocationsMutex.Unlock() 107 | if fake.invocations == nil { 108 | fake.invocations = map[string][][]interface{}{} 109 | } 110 | if fake.invocations[key] == nil { 111 | fake.invocations[key] = [][]interface{}{} 112 | } 113 | fake.invocations[key] = append(fake.invocations[key], args) 114 | } 115 | -------------------------------------------------------------------------------- /out/outfakes/validation.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package outfakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type Validation struct { 9 | ValidateStub func() error 10 | validateMutex sync.RWMutex 11 | validateArgsForCall []struct { 12 | } 13 | validateReturns struct { 14 | result1 error 15 | } 16 | validateReturnsOnCall map[int]struct { 17 | result1 error 18 | } 19 | invocations map[string][][]interface{} 20 | invocationsMutex sync.RWMutex 21 | } 22 | 23 | func (fake *Validation) Validate() error { 24 | fake.validateMutex.Lock() 25 | ret, specificReturn := fake.validateReturnsOnCall[len(fake.validateArgsForCall)] 26 | fake.validateArgsForCall = append(fake.validateArgsForCall, struct { 27 | }{}) 28 | stub := fake.ValidateStub 29 | fakeReturns := fake.validateReturns 30 | fake.recordInvocation("Validate", []interface{}{}) 31 | fake.validateMutex.Unlock() 32 | if stub != nil { 33 | return stub() 34 | } 35 | if specificReturn { 36 | return ret.result1 37 | } 38 | return fakeReturns.result1 39 | } 40 | 41 | func (fake *Validation) ValidateCallCount() int { 42 | fake.validateMutex.RLock() 43 | defer fake.validateMutex.RUnlock() 44 | return len(fake.validateArgsForCall) 45 | } 46 | 47 | func (fake *Validation) ValidateCalls(stub func() error) { 48 | fake.validateMutex.Lock() 49 | defer fake.validateMutex.Unlock() 50 | fake.ValidateStub = stub 51 | } 52 | 53 | func (fake *Validation) ValidateReturns(result1 error) { 54 | fake.validateMutex.Lock() 55 | defer fake.validateMutex.Unlock() 56 | fake.ValidateStub = nil 57 | fake.validateReturns = struct { 58 | result1 error 59 | }{result1} 60 | } 61 | 62 | func (fake *Validation) ValidateReturnsOnCall(i int, result1 error) { 63 | fake.validateMutex.Lock() 64 | defer fake.validateMutex.Unlock() 65 | fake.ValidateStub = nil 66 | if fake.validateReturnsOnCall == nil { 67 | fake.validateReturnsOnCall = make(map[int]struct { 68 | result1 error 69 | }) 70 | } 71 | fake.validateReturnsOnCall[i] = struct { 72 | result1 error 73 | }{result1} 74 | } 75 | 76 | func (fake *Validation) Invocations() map[string][][]interface{} { 77 | fake.invocationsMutex.RLock() 78 | defer fake.invocationsMutex.RUnlock() 79 | fake.validateMutex.RLock() 80 | defer fake.validateMutex.RUnlock() 81 | copiedInvocations := map[string][][]interface{}{} 82 | for key, value := range fake.invocations { 83 | copiedInvocations[key] = value 84 | } 85 | return copiedInvocations 86 | } 87 | 88 | func (fake *Validation) recordInvocation(key string, args []interface{}) { 89 | fake.invocationsMutex.Lock() 90 | defer fake.invocationsMutex.Unlock() 91 | if fake.invocations == nil { 92 | fake.invocations = map[string][][]interface{}{} 93 | } 94 | if fake.invocations[key] == nil { 95 | fake.invocations[key] = [][]interface{}{} 96 | } 97 | fake.invocations[key] = append(fake.invocations[key], args) 98 | } 99 | -------------------------------------------------------------------------------- /out/package.go: -------------------------------------------------------------------------------- 1 | package out 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /out/release/dependency_specifiers.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | 6 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 9 | ) 10 | 11 | type DependencySpecifiersCreator struct { 12 | logger logger.Logger 13 | pivnet dependencySpecifiersCreatorClient 14 | metadata metadata.Metadata 15 | productSlug string 16 | } 17 | 18 | func NewDependencySpecifiersCreator( 19 | logger logger.Logger, 20 | pivnetClient dependencySpecifiersCreatorClient, 21 | metadata metadata.Metadata, 22 | productSlug string, 23 | ) DependencySpecifiersCreator { 24 | return DependencySpecifiersCreator{ 25 | logger: logger, 26 | pivnet: pivnetClient, 27 | metadata: metadata, 28 | productSlug: productSlug, 29 | } 30 | } 31 | 32 | //counterfeiter:generate --fake-name DependencySpecifiersCreatorClient . dependencySpecifiersCreatorClient 33 | type dependencySpecifiersCreatorClient interface { 34 | CreateDependencySpecifier(productSlug string, releaseID int, dependentProductSlug string, specifier string) (pivnet.DependencySpecifier, error) 35 | } 36 | 37 | func (rf DependencySpecifiersCreator) CreateDependencySpecifiers(release pivnet.Release) error { 38 | for _, d := range rf.metadata.DependencySpecifiers { 39 | rf.logger.Info(fmt.Sprintf( 40 | "Creating dependency specifier for: '%s/%s'", 41 | d.ProductSlug, 42 | d.Specifier, 43 | )) 44 | _, err := rf.pivnet.CreateDependencySpecifier(rf.productSlug, release.ID, d.ProductSlug, d.Specifier) 45 | if err != nil { 46 | return err 47 | } 48 | } 49 | 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /out/release/dependency_specifiers_test.go: -------------------------------------------------------------------------------- 1 | package release_test 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/pivotal-cf/go-pivnet/v7" 8 | "github.com/pivotal-cf/go-pivnet/v7/logger" 9 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 10 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 11 | "github.com/pivotal-cf/pivnet-resource/v3/out/release" 12 | "github.com/pivotal-cf/pivnet-resource/v3/out/release/releasefakes" 13 | 14 | . "github.com/onsi/ginkgo" 15 | . "github.com/onsi/gomega" 16 | ) 17 | 18 | var _ = Describe("DependencySpecifiersCreator", func() { 19 | Describe("CreateDependencySpecifiers", func() { 20 | var ( 21 | fakeLogger logger.Logger 22 | 23 | pivnetClient *releasefakes.DependencySpecifiersCreatorClient 24 | 25 | mdata metadata.Metadata 26 | 27 | productSlug string 28 | pivnetRelease pivnet.Release 29 | 30 | dependencySpecifiersCreator release.DependencySpecifiersCreator 31 | ) 32 | 33 | BeforeEach(func() { 34 | logger := log.New(GinkgoWriter, "", log.LstdFlags) 35 | fakeLogger = logshim.NewLogShim(logger, logger, true) 36 | 37 | pivnetClient = &releasefakes.DependencySpecifiersCreatorClient{} 38 | 39 | productSlug = "some-product-slug" 40 | 41 | pivnetRelease = pivnet.Release{ 42 | Availability: "some-value", 43 | ID: 1337, 44 | Version: "some-version", 45 | EULA: &pivnet.EULA{ 46 | Slug: "a_eula_slug", 47 | }, 48 | } 49 | 50 | mdata = metadata.Metadata{ 51 | Release: &metadata.Release{ 52 | Availability: "some-value", 53 | Version: "some-version", 54 | EULASlug: "a_eula_slug", 55 | }, 56 | ProductFiles: []metadata.ProductFile{}, 57 | } 58 | 59 | pivnetClient.CreateDependencySpecifierReturns(pivnet.DependencySpecifier{}, nil) 60 | }) 61 | 62 | JustBeforeEach(func() { 63 | dependencySpecifiersCreator = release.NewDependencySpecifiersCreator( 64 | fakeLogger, 65 | pivnetClient, 66 | mdata, 67 | productSlug, 68 | ) 69 | }) 70 | 71 | Context("when dependency specifiers are provided", func() { 72 | BeforeEach(func() { 73 | mdata.DependencySpecifiers = []metadata.DependencySpecifier{ 74 | { 75 | ID: 9876, 76 | Specifier: "1.2.*", 77 | ProductSlug: "some-dependent-product", 78 | }, 79 | { 80 | ID: 8765, 81 | Specifier: "2.3.*", 82 | ProductSlug: "some-other-dependent-product", 83 | }, 84 | } 85 | }) 86 | 87 | It("creates the dependencies", func() { 88 | err := dependencySpecifiersCreator.CreateDependencySpecifiers(pivnetRelease) 89 | Expect(err).NotTo(HaveOccurred()) 90 | 91 | Expect(pivnetClient.CreateDependencySpecifierCallCount()).To(Equal(2)) 92 | }) 93 | 94 | Context("when creating dependency specifier returns an error ", func() { 95 | var ( 96 | expectedErr error 97 | ) 98 | 99 | BeforeEach(func() { 100 | expectedErr = fmt.Errorf("boom") 101 | pivnetClient.CreateDependencySpecifierReturns(pivnet.DependencySpecifier{}, expectedErr) 102 | }) 103 | 104 | It("returns an error", func() { 105 | err := dependencySpecifiersCreator.CreateDependencySpecifiers(pivnetRelease) 106 | Expect(err).To(HaveOccurred()) 107 | 108 | Expect(err).To(Equal(expectedErr)) 109 | }) 110 | }) 111 | }) 112 | }) 113 | }) 114 | -------------------------------------------------------------------------------- /out/release/init_test.go: -------------------------------------------------------------------------------- 1 | package release_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestRelease(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Release Suite") 13 | } 14 | -------------------------------------------------------------------------------- /out/release/package.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /out/release/release_dependencies.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | 6 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 9 | ) 10 | 11 | type ReleaseDependenciesAdder struct { 12 | logger logger.Logger 13 | pivnet releaseDependenciesAdderClient 14 | metadata metadata.Metadata 15 | productSlug string 16 | } 17 | 18 | func NewReleaseDependenciesAdder( 19 | logger logger.Logger, 20 | pivnetClient releaseDependenciesAdderClient, 21 | metadata metadata.Metadata, 22 | productSlug string, 23 | ) ReleaseDependenciesAdder { 24 | return ReleaseDependenciesAdder{ 25 | logger: logger, 26 | pivnet: pivnetClient, 27 | metadata: metadata, 28 | productSlug: productSlug, 29 | } 30 | } 31 | 32 | //counterfeiter:generate --fake-name ReleaseDependenciesAdderClient . releaseDependenciesAdderClient 33 | type releaseDependenciesAdderClient interface { 34 | AddReleaseDependency(productSlug string, releaseID int, dependentReleaseID int) error 35 | GetRelease(productSlug string, releaseVersion string) (pivnet.Release, error) 36 | } 37 | 38 | func (rf ReleaseDependenciesAdder) AddReleaseDependencies(release pivnet.Release) error { 39 | for i, d := range rf.metadata.Dependencies { 40 | dependentReleaseID := d.Release.ID 41 | if dependentReleaseID == 0 { 42 | if d.Release.Version == "" || d.Release.Product.Slug == "" { 43 | return fmt.Errorf( 44 | "Either ReleaseID or release version and product slug must be provided for dependencies[%d]", 45 | i, 46 | ) 47 | } 48 | 49 | rf.logger.Info(fmt.Sprintf( 50 | "Looking up dependent release ID for: '%s/%s'", 51 | d.Release.Product.Slug, 52 | d.Release.Version, 53 | )) 54 | r, err := rf.pivnet.GetRelease(d.Release.Product.Slug, d.Release.Version) 55 | if err != nil { 56 | return err 57 | } 58 | dependentReleaseID = r.ID 59 | } 60 | 61 | rf.logger.Info(fmt.Sprintf( 62 | "Adding dependent release with ID: %d", 63 | dependentReleaseID, 64 | )) 65 | err := rf.pivnet.AddReleaseDependency(rf.productSlug, release.ID, dependentReleaseID) 66 | if err != nil { 67 | return err 68 | } 69 | } 70 | 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /out/release/release_file_groups.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | 6 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 9 | ) 10 | 11 | type ReleaseFileGroupsAdder struct { 12 | logger logger.Logger 13 | pivnet releaseFileGroupsAdderClient 14 | metadata metadata.Metadata 15 | productSlug string 16 | } 17 | 18 | func NewReleaseFileGroupsAdder( 19 | logger logger.Logger, 20 | pivnetClient releaseFileGroupsAdderClient, 21 | metadata metadata.Metadata, 22 | productSlug string, 23 | ) ReleaseFileGroupsAdder { 24 | return ReleaseFileGroupsAdder{ 25 | logger: logger, 26 | pivnet: pivnetClient, 27 | metadata: metadata, 28 | productSlug: productSlug, 29 | } 30 | } 31 | 32 | //counterfeiter:generate --fake-name ReleaseFileGroupsAdderClient . releaseFileGroupsAdderClient 33 | type releaseFileGroupsAdderClient interface { 34 | AddFileGroup(productSlug string, releaseID int, fileGroupID int) error 35 | CreateFileGroup(config pivnet.CreateFileGroupConfig) (pivnet.FileGroup, error) 36 | AddToFileGroup(productSlug string, fileGroupID int, productFileID int) error 37 | } 38 | 39 | func (rf ReleaseFileGroupsAdder) AddReleaseFileGroups(release pivnet.Release) error { 40 | for _, fileGroup := range rf.metadata.FileGroups { 41 | fileGroupID := fileGroup.ID 42 | if fileGroupID == 0 { 43 | rf.logger.Info(fmt.Sprintf( 44 | "Creating file group with name: %s", 45 | fileGroup.Name, 46 | )) 47 | 48 | g, err := rf.pivnet.CreateFileGroup(pivnet.CreateFileGroupConfig{ 49 | ProductSlug: rf.productSlug, 50 | Name: fileGroup.Name, 51 | }) 52 | 53 | if err != nil { 54 | return err 55 | } 56 | 57 | fileGroupID = g.ID 58 | 59 | for _, pf := range fileGroup.ProductFiles { 60 | rf.logger.Info(fmt.Sprintf( 61 | "Adding product file %d to file group with ID: %d", 62 | pf.ID, 63 | fileGroupID, 64 | )) 65 | 66 | err := rf.pivnet.AddToFileGroup(rf.productSlug, fileGroupID, pf.ID) 67 | 68 | if err != nil { 69 | return err 70 | } 71 | } 72 | } 73 | 74 | rf.logger.Info(fmt.Sprintf( 75 | "Adding file group with ID: %d", 76 | fileGroupID, 77 | )) 78 | err := rf.pivnet.AddFileGroup(rf.productSlug, release.ID, fileGroupID) 79 | if err != nil { 80 | return err 81 | } 82 | } 83 | 84 | return nil 85 | } 86 | -------------------------------------------------------------------------------- /out/release/release_finalizer.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | 6 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 9 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 10 | "github.com/pivotal-cf/pivnet-resource/v3/versions" 11 | ) 12 | 13 | type ReleaseFinalizer struct { 14 | logger logger.Logger 15 | pivnet finalizerClient 16 | metadata metadata.Metadata 17 | params concourse.OutParams 18 | sourcesDir string 19 | productSlug string 20 | } 21 | 22 | func NewFinalizer( 23 | pivnetClient finalizerClient, 24 | logger logger.Logger, 25 | params concourse.OutParams, 26 | metadata metadata.Metadata, 27 | sourcesDir, 28 | productSlug string, 29 | ) ReleaseFinalizer { 30 | return ReleaseFinalizer{ 31 | pivnet: pivnetClient, 32 | logger: logger, 33 | params: params, 34 | metadata: metadata, 35 | sourcesDir: sourcesDir, 36 | productSlug: productSlug, 37 | } 38 | } 39 | 40 | //counterfeiter:generate --fake-name FinalizerClient . finalizerClient 41 | type finalizerClient interface { 42 | GetRelease(productSlug string, releaseVersion string) (pivnet.Release, error) 43 | } 44 | 45 | func (rf ReleaseFinalizer) Finalize(productSlug string, releaseVersion string) (concourse.OutResponse, error) { 46 | newRelease, err := rf.pivnet.GetRelease(productSlug, releaseVersion) 47 | if err != nil { 48 | return concourse.OutResponse{}, err 49 | } 50 | 51 | outputVersion, err := versions.CombineVersionAndFingerprint(newRelease.Version, newRelease.SoftwareFilesUpdatedAt) 52 | if err != nil { 53 | return concourse.OutResponse{}, err // this will never return an error 54 | } 55 | 56 | metadata := []concourse.Metadata{ 57 | {Name: "version", Value: newRelease.Version}, 58 | {Name: "release_type", Value: string(newRelease.ReleaseType)}, 59 | {Name: "release_date", Value: newRelease.ReleaseDate}, 60 | {Name: "description", Value: newRelease.Description}, 61 | {Name: "release_notes_url", Value: newRelease.ReleaseNotesURL}, 62 | {Name: "availability", Value: newRelease.Availability}, 63 | {Name: "controlled", Value: fmt.Sprintf("%t", newRelease.Controlled)}, 64 | {Name: "eccn", Value: newRelease.ECCN}, 65 | {Name: "license_exception", Value: newRelease.LicenseException}, 66 | {Name: "end_of_support_date", Value: newRelease.EndOfSupportDate}, 67 | {Name: "end_of_guidance_date", Value: newRelease.EndOfGuidanceDate}, 68 | {Name: "end_of_availability_date", Value: newRelease.EndOfAvailabilityDate}, 69 | } 70 | if newRelease.EULA != nil { 71 | metadata = append( 72 | metadata, 73 | concourse.Metadata{Name: "eula_slug", Value: newRelease.EULA.Slug}) 74 | } 75 | 76 | return concourse.OutResponse{ 77 | Version: concourse.Version{ 78 | ProductVersion: outputVersion, 79 | }, 80 | Metadata: metadata, 81 | }, nil 82 | } 83 | -------------------------------------------------------------------------------- /out/release/release_finalizer_test.go: -------------------------------------------------------------------------------- 1 | package release_test 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | 7 | "github.com/pivotal-cf/go-pivnet/v7" 8 | "github.com/pivotal-cf/go-pivnet/v7/logger" 9 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 10 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 11 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 12 | "github.com/pivotal-cf/pivnet-resource/v3/out/release" 13 | "github.com/pivotal-cf/pivnet-resource/v3/out/release/releasefakes" 14 | 15 | . "github.com/onsi/ginkgo" 16 | . "github.com/onsi/gomega" 17 | ) 18 | 19 | var _ = Describe("ReleaseFinalizer", func() { 20 | Describe("Finalize", func() { 21 | var ( 22 | fakeLogger logger.Logger 23 | 24 | fakePivnet *releasefakes.FinalizerClient 25 | params concourse.OutParams 26 | 27 | mdata metadata.Metadata 28 | 29 | productSlug string 30 | pivnetRelease pivnet.Release 31 | 32 | releaseErr error 33 | 34 | finalizer release.ReleaseFinalizer 35 | ) 36 | 37 | BeforeEach(func() { 38 | logger := log.New(GinkgoWriter, "", log.LstdFlags) 39 | fakeLogger = logshim.NewLogShim(logger, logger, true) 40 | 41 | fakePivnet = &releasefakes.FinalizerClient{} 42 | 43 | params = concourse.OutParams{} 44 | 45 | productSlug = "some-product-slug" 46 | 47 | pivnetRelease = pivnet.Release{ 48 | Availability: "Admins Only", 49 | ID: 1337, 50 | Version: "some-version", 51 | EULA: &pivnet.EULA{ 52 | Slug: "a_eula_slug", 53 | }, 54 | SoftwareFilesUpdatedAt: "some-new-time", 55 | } 56 | 57 | mdata = metadata.Metadata{ 58 | Release: &metadata.Release{ 59 | Availability: "some-value", 60 | Version: "some-version", 61 | EULASlug: "a_eula_slug", 62 | }, 63 | ProductFiles: []metadata.ProductFile{}, 64 | } 65 | 66 | releaseErr = nil 67 | }) 68 | 69 | JustBeforeEach(func() { 70 | finalizer = release.NewFinalizer( 71 | fakePivnet, 72 | fakeLogger, 73 | params, 74 | mdata, 75 | "/some/sources/dir", 76 | productSlug, 77 | ) 78 | 79 | fakePivnet.GetReleaseReturns(pivnetRelease, releaseErr) 80 | }) 81 | 82 | It("returns a final concourse out response", func() { 83 | response, err := finalizer.Finalize(productSlug, pivnetRelease.Version) 84 | Expect(err).NotTo(HaveOccurred()) 85 | 86 | Expect(response.Version).To(Equal(concourse.Version{ 87 | ProductVersion: "some-version#some-new-time", 88 | })) 89 | 90 | Expect(response.Metadata).To(ContainElement(concourse.Metadata{Name: "version", Value: "some-version"})) 91 | Expect(response.Metadata).To(ContainElement(concourse.Metadata{Name: "controlled", Value: "false"})) 92 | Expect(response.Metadata).To(ContainElement(concourse.Metadata{Name: "eula_slug", Value: "a_eula_slug"})) 93 | }) 94 | 95 | Context("when getting the release returns an error", func() { 96 | BeforeEach(func() { 97 | releaseErr = errors.New("release error") 98 | }) 99 | 100 | It("forwards the error", func() { 101 | _, err := finalizer.Finalize(productSlug, pivnetRelease.Version) 102 | Expect(err).To(HaveOccurred()) 103 | 104 | Expect(err).To(Equal(releaseErr)) 105 | }) 106 | }) 107 | }) 108 | }) 109 | -------------------------------------------------------------------------------- /out/release/release_finder.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import "github.com/pivotal-cf/go-pivnet/v7" 4 | 5 | type ReleaseFinder struct { 6 | pivnet finderClient 7 | productSlug string 8 | } 9 | 10 | //counterfeiter:generate --fake-name=FinderClient . finderClient 11 | type finderClient interface { 12 | FindRelease(productSlug string, releaseID int) (pivnet.Release, error) 13 | } 14 | 15 | func NewReleaseFinder( 16 | pivnet finderClient, 17 | productSlug string, 18 | ) ReleaseFinder { 19 | return ReleaseFinder{ 20 | pivnet: pivnet, 21 | productSlug: productSlug, 22 | } 23 | } 24 | 25 | func (rf ReleaseFinder) Find(i int) (pivnet.Release, error) { 26 | return rf.pivnet.FindRelease(rf.productSlug, i) 27 | } 28 | -------------------------------------------------------------------------------- /out/release/release_finder_test.go: -------------------------------------------------------------------------------- 1 | package release_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | "github.com/pivotal-cf/go-pivnet/v7" 6 | "github.com/pivotal-cf/pivnet-resource/v3/out/release" 7 | "github.com/pivotal-cf/pivnet-resource/v3/out/release/releasefakes" 8 | 9 | . "github.com/onsi/gomega" 10 | ) 11 | 12 | var _ = Describe("ReleaseFinder", func() { 13 | var ( 14 | pivnetClient *releasefakes.FinderClient 15 | finder release.ReleaseFinder 16 | releaseID int 17 | pivnetRelease pivnet.Release 18 | finderErr error 19 | productSlug string 20 | ) 21 | BeforeEach(func() { 22 | pivnetClient = &releasefakes.FinderClient{} 23 | finderErr = nil 24 | productSlug = "special-product" 25 | }) 26 | 27 | Describe("Find", func() { 28 | 29 | BeforeEach(func() { 30 | finder = release.NewReleaseFinder( 31 | pivnetClient, 32 | productSlug, 33 | ) 34 | releaseID = 123 35 | pivnetRelease = pivnet.Release{ 36 | ID: releaseID, 37 | } 38 | 39 | pivnetClient.FindReleaseReturns(pivnetRelease, finderErr) 40 | }) 41 | 42 | It("finds a release", func() { 43 | r, err := finder.Find(releaseID) 44 | Expect(err).NotTo(HaveOccurred()) 45 | 46 | slug, id := pivnetClient.FindReleaseArgsForCall(0) 47 | Expect(slug).To(Equal(productSlug)) 48 | Expect(id).To(Equal(releaseID)) 49 | 50 | Expect(r).To(Equal(pivnet.Release{ID: releaseID})) 51 | }) 52 | }) 53 | }) 54 | -------------------------------------------------------------------------------- /out/release/releasefakes/fake_filter.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type FakeFilter struct { 11 | ReleasesByVersionStub func([]pivnet.Release, string) ([]pivnet.Release, error) 12 | releasesByVersionMutex sync.RWMutex 13 | releasesByVersionArgsForCall []struct { 14 | arg1 []pivnet.Release 15 | arg2 string 16 | } 17 | releasesByVersionReturns struct { 18 | result1 []pivnet.Release 19 | result2 error 20 | } 21 | releasesByVersionReturnsOnCall map[int]struct { 22 | result1 []pivnet.Release 23 | result2 error 24 | } 25 | invocations map[string][][]interface{} 26 | invocationsMutex sync.RWMutex 27 | } 28 | 29 | func (fake *FakeFilter) ReleasesByVersion(arg1 []pivnet.Release, arg2 string) ([]pivnet.Release, error) { 30 | var arg1Copy []pivnet.Release 31 | if arg1 != nil { 32 | arg1Copy = make([]pivnet.Release, len(arg1)) 33 | copy(arg1Copy, arg1) 34 | } 35 | fake.releasesByVersionMutex.Lock() 36 | ret, specificReturn := fake.releasesByVersionReturnsOnCall[len(fake.releasesByVersionArgsForCall)] 37 | fake.releasesByVersionArgsForCall = append(fake.releasesByVersionArgsForCall, struct { 38 | arg1 []pivnet.Release 39 | arg2 string 40 | }{arg1Copy, arg2}) 41 | stub := fake.ReleasesByVersionStub 42 | fakeReturns := fake.releasesByVersionReturns 43 | fake.recordInvocation("ReleasesByVersion", []interface{}{arg1Copy, arg2}) 44 | fake.releasesByVersionMutex.Unlock() 45 | if stub != nil { 46 | return stub(arg1, arg2) 47 | } 48 | if specificReturn { 49 | return ret.result1, ret.result2 50 | } 51 | return fakeReturns.result1, fakeReturns.result2 52 | } 53 | 54 | func (fake *FakeFilter) ReleasesByVersionCallCount() int { 55 | fake.releasesByVersionMutex.RLock() 56 | defer fake.releasesByVersionMutex.RUnlock() 57 | return len(fake.releasesByVersionArgsForCall) 58 | } 59 | 60 | func (fake *FakeFilter) ReleasesByVersionCalls(stub func([]pivnet.Release, string) ([]pivnet.Release, error)) { 61 | fake.releasesByVersionMutex.Lock() 62 | defer fake.releasesByVersionMutex.Unlock() 63 | fake.ReleasesByVersionStub = stub 64 | } 65 | 66 | func (fake *FakeFilter) ReleasesByVersionArgsForCall(i int) ([]pivnet.Release, string) { 67 | fake.releasesByVersionMutex.RLock() 68 | defer fake.releasesByVersionMutex.RUnlock() 69 | argsForCall := fake.releasesByVersionArgsForCall[i] 70 | return argsForCall.arg1, argsForCall.arg2 71 | } 72 | 73 | func (fake *FakeFilter) ReleasesByVersionReturns(result1 []pivnet.Release, result2 error) { 74 | fake.releasesByVersionMutex.Lock() 75 | defer fake.releasesByVersionMutex.Unlock() 76 | fake.ReleasesByVersionStub = nil 77 | fake.releasesByVersionReturns = struct { 78 | result1 []pivnet.Release 79 | result2 error 80 | }{result1, result2} 81 | } 82 | 83 | func (fake *FakeFilter) ReleasesByVersionReturnsOnCall(i int, result1 []pivnet.Release, result2 error) { 84 | fake.releasesByVersionMutex.Lock() 85 | defer fake.releasesByVersionMutex.Unlock() 86 | fake.ReleasesByVersionStub = nil 87 | if fake.releasesByVersionReturnsOnCall == nil { 88 | fake.releasesByVersionReturnsOnCall = make(map[int]struct { 89 | result1 []pivnet.Release 90 | result2 error 91 | }) 92 | } 93 | fake.releasesByVersionReturnsOnCall[i] = struct { 94 | result1 []pivnet.Release 95 | result2 error 96 | }{result1, result2} 97 | } 98 | 99 | func (fake *FakeFilter) Invocations() map[string][][]interface{} { 100 | fake.invocationsMutex.RLock() 101 | defer fake.invocationsMutex.RUnlock() 102 | fake.releasesByVersionMutex.RLock() 103 | defer fake.releasesByVersionMutex.RUnlock() 104 | copiedInvocations := map[string][][]interface{}{} 105 | for key, value := range fake.invocations { 106 | copiedInvocations[key] = value 107 | } 108 | return copiedInvocations 109 | } 110 | 111 | func (fake *FakeFilter) recordInvocation(key string, args []interface{}) { 112 | fake.invocationsMutex.Lock() 113 | defer fake.invocationsMutex.Unlock() 114 | if fake.invocations == nil { 115 | fake.invocations = map[string][][]interface{}{} 116 | } 117 | if fake.invocations[key] == nil { 118 | fake.invocations[key] = [][]interface{}{} 119 | } 120 | fake.invocations[key] = append(fake.invocations[key], args) 121 | } 122 | -------------------------------------------------------------------------------- /out/release/releasefakes/fake_semver_converter.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | 7 | "github.com/blang/semver" 8 | ) 9 | 10 | type FakeSemverConverter struct { 11 | ToValidSemverStub func(string) (semver.Version, error) 12 | toValidSemverMutex sync.RWMutex 13 | toValidSemverArgsForCall []struct { 14 | arg1 string 15 | } 16 | toValidSemverReturns struct { 17 | result1 semver.Version 18 | result2 error 19 | } 20 | toValidSemverReturnsOnCall map[int]struct { 21 | result1 semver.Version 22 | result2 error 23 | } 24 | invocations map[string][][]interface{} 25 | invocationsMutex sync.RWMutex 26 | } 27 | 28 | func (fake *FakeSemverConverter) ToValidSemver(arg1 string) (semver.Version, error) { 29 | fake.toValidSemverMutex.Lock() 30 | ret, specificReturn := fake.toValidSemverReturnsOnCall[len(fake.toValidSemverArgsForCall)] 31 | fake.toValidSemverArgsForCall = append(fake.toValidSemverArgsForCall, struct { 32 | arg1 string 33 | }{arg1}) 34 | stub := fake.ToValidSemverStub 35 | fakeReturns := fake.toValidSemverReturns 36 | fake.recordInvocation("ToValidSemver", []interface{}{arg1}) 37 | fake.toValidSemverMutex.Unlock() 38 | if stub != nil { 39 | return stub(arg1) 40 | } 41 | if specificReturn { 42 | return ret.result1, ret.result2 43 | } 44 | return fakeReturns.result1, fakeReturns.result2 45 | } 46 | 47 | func (fake *FakeSemverConverter) ToValidSemverCallCount() int { 48 | fake.toValidSemverMutex.RLock() 49 | defer fake.toValidSemverMutex.RUnlock() 50 | return len(fake.toValidSemverArgsForCall) 51 | } 52 | 53 | func (fake *FakeSemverConverter) ToValidSemverCalls(stub func(string) (semver.Version, error)) { 54 | fake.toValidSemverMutex.Lock() 55 | defer fake.toValidSemverMutex.Unlock() 56 | fake.ToValidSemverStub = stub 57 | } 58 | 59 | func (fake *FakeSemverConverter) ToValidSemverArgsForCall(i int) string { 60 | fake.toValidSemverMutex.RLock() 61 | defer fake.toValidSemverMutex.RUnlock() 62 | argsForCall := fake.toValidSemverArgsForCall[i] 63 | return argsForCall.arg1 64 | } 65 | 66 | func (fake *FakeSemverConverter) ToValidSemverReturns(result1 semver.Version, result2 error) { 67 | fake.toValidSemverMutex.Lock() 68 | defer fake.toValidSemverMutex.Unlock() 69 | fake.ToValidSemverStub = nil 70 | fake.toValidSemverReturns = struct { 71 | result1 semver.Version 72 | result2 error 73 | }{result1, result2} 74 | } 75 | 76 | func (fake *FakeSemverConverter) ToValidSemverReturnsOnCall(i int, result1 semver.Version, result2 error) { 77 | fake.toValidSemverMutex.Lock() 78 | defer fake.toValidSemverMutex.Unlock() 79 | fake.ToValidSemverStub = nil 80 | if fake.toValidSemverReturnsOnCall == nil { 81 | fake.toValidSemverReturnsOnCall = make(map[int]struct { 82 | result1 semver.Version 83 | result2 error 84 | }) 85 | } 86 | fake.toValidSemverReturnsOnCall[i] = struct { 87 | result1 semver.Version 88 | result2 error 89 | }{result1, result2} 90 | } 91 | 92 | func (fake *FakeSemverConverter) Invocations() map[string][][]interface{} { 93 | fake.invocationsMutex.RLock() 94 | defer fake.invocationsMutex.RUnlock() 95 | fake.toValidSemverMutex.RLock() 96 | defer fake.toValidSemverMutex.RUnlock() 97 | copiedInvocations := map[string][][]interface{}{} 98 | for key, value := range fake.invocations { 99 | copiedInvocations[key] = value 100 | } 101 | return copiedInvocations 102 | } 103 | 104 | func (fake *FakeSemverConverter) recordInvocation(key string, args []interface{}) { 105 | fake.invocationsMutex.Lock() 106 | defer fake.invocationsMutex.Unlock() 107 | if fake.invocations == nil { 108 | fake.invocations = map[string][][]interface{}{} 109 | } 110 | if fake.invocations[key] == nil { 111 | fake.invocations[key] = [][]interface{}{} 112 | } 113 | fake.invocations[key] = append(fake.invocations[key], args) 114 | } 115 | -------------------------------------------------------------------------------- /out/release/releasefakes/finalizer_client.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type FinalizerClient struct { 11 | GetReleaseStub func(string, string) (pivnet.Release, error) 12 | getReleaseMutex sync.RWMutex 13 | getReleaseArgsForCall []struct { 14 | arg1 string 15 | arg2 string 16 | } 17 | getReleaseReturns struct { 18 | result1 pivnet.Release 19 | result2 error 20 | } 21 | getReleaseReturnsOnCall map[int]struct { 22 | result1 pivnet.Release 23 | result2 error 24 | } 25 | invocations map[string][][]interface{} 26 | invocationsMutex sync.RWMutex 27 | } 28 | 29 | func (fake *FinalizerClient) GetRelease(arg1 string, arg2 string) (pivnet.Release, error) { 30 | fake.getReleaseMutex.Lock() 31 | ret, specificReturn := fake.getReleaseReturnsOnCall[len(fake.getReleaseArgsForCall)] 32 | fake.getReleaseArgsForCall = append(fake.getReleaseArgsForCall, struct { 33 | arg1 string 34 | arg2 string 35 | }{arg1, arg2}) 36 | stub := fake.GetReleaseStub 37 | fakeReturns := fake.getReleaseReturns 38 | fake.recordInvocation("GetRelease", []interface{}{arg1, arg2}) 39 | fake.getReleaseMutex.Unlock() 40 | if stub != nil { 41 | return stub(arg1, arg2) 42 | } 43 | if specificReturn { 44 | return ret.result1, ret.result2 45 | } 46 | return fakeReturns.result1, fakeReturns.result2 47 | } 48 | 49 | func (fake *FinalizerClient) GetReleaseCallCount() int { 50 | fake.getReleaseMutex.RLock() 51 | defer fake.getReleaseMutex.RUnlock() 52 | return len(fake.getReleaseArgsForCall) 53 | } 54 | 55 | func (fake *FinalizerClient) GetReleaseCalls(stub func(string, string) (pivnet.Release, error)) { 56 | fake.getReleaseMutex.Lock() 57 | defer fake.getReleaseMutex.Unlock() 58 | fake.GetReleaseStub = stub 59 | } 60 | 61 | func (fake *FinalizerClient) GetReleaseArgsForCall(i int) (string, string) { 62 | fake.getReleaseMutex.RLock() 63 | defer fake.getReleaseMutex.RUnlock() 64 | argsForCall := fake.getReleaseArgsForCall[i] 65 | return argsForCall.arg1, argsForCall.arg2 66 | } 67 | 68 | func (fake *FinalizerClient) GetReleaseReturns(result1 pivnet.Release, result2 error) { 69 | fake.getReleaseMutex.Lock() 70 | defer fake.getReleaseMutex.Unlock() 71 | fake.GetReleaseStub = nil 72 | fake.getReleaseReturns = struct { 73 | result1 pivnet.Release 74 | result2 error 75 | }{result1, result2} 76 | } 77 | 78 | func (fake *FinalizerClient) GetReleaseReturnsOnCall(i int, result1 pivnet.Release, result2 error) { 79 | fake.getReleaseMutex.Lock() 80 | defer fake.getReleaseMutex.Unlock() 81 | fake.GetReleaseStub = nil 82 | if fake.getReleaseReturnsOnCall == nil { 83 | fake.getReleaseReturnsOnCall = make(map[int]struct { 84 | result1 pivnet.Release 85 | result2 error 86 | }) 87 | } 88 | fake.getReleaseReturnsOnCall[i] = struct { 89 | result1 pivnet.Release 90 | result2 error 91 | }{result1, result2} 92 | } 93 | 94 | func (fake *FinalizerClient) Invocations() map[string][][]interface{} { 95 | fake.invocationsMutex.RLock() 96 | defer fake.invocationsMutex.RUnlock() 97 | fake.getReleaseMutex.RLock() 98 | defer fake.getReleaseMutex.RUnlock() 99 | copiedInvocations := map[string][][]interface{}{} 100 | for key, value := range fake.invocations { 101 | copiedInvocations[key] = value 102 | } 103 | return copiedInvocations 104 | } 105 | 106 | func (fake *FinalizerClient) recordInvocation(key string, args []interface{}) { 107 | fake.invocationsMutex.Lock() 108 | defer fake.invocationsMutex.Unlock() 109 | if fake.invocations == nil { 110 | fake.invocations = map[string][][]interface{}{} 111 | } 112 | if fake.invocations[key] == nil { 113 | fake.invocations[key] = [][]interface{}{} 114 | } 115 | fake.invocations[key] = append(fake.invocations[key], args) 116 | } 117 | -------------------------------------------------------------------------------- /out/release/releasefakes/finder_client.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type FinderClient struct { 11 | FindReleaseStub func(string, int) (pivnet.Release, error) 12 | findReleaseMutex sync.RWMutex 13 | findReleaseArgsForCall []struct { 14 | arg1 string 15 | arg2 int 16 | } 17 | findReleaseReturns struct { 18 | result1 pivnet.Release 19 | result2 error 20 | } 21 | findReleaseReturnsOnCall map[int]struct { 22 | result1 pivnet.Release 23 | result2 error 24 | } 25 | invocations map[string][][]interface{} 26 | invocationsMutex sync.RWMutex 27 | } 28 | 29 | func (fake *FinderClient) FindRelease(arg1 string, arg2 int) (pivnet.Release, error) { 30 | fake.findReleaseMutex.Lock() 31 | ret, specificReturn := fake.findReleaseReturnsOnCall[len(fake.findReleaseArgsForCall)] 32 | fake.findReleaseArgsForCall = append(fake.findReleaseArgsForCall, struct { 33 | arg1 string 34 | arg2 int 35 | }{arg1, arg2}) 36 | stub := fake.FindReleaseStub 37 | fakeReturns := fake.findReleaseReturns 38 | fake.recordInvocation("FindRelease", []interface{}{arg1, arg2}) 39 | fake.findReleaseMutex.Unlock() 40 | if stub != nil { 41 | return stub(arg1, arg2) 42 | } 43 | if specificReturn { 44 | return ret.result1, ret.result2 45 | } 46 | return fakeReturns.result1, fakeReturns.result2 47 | } 48 | 49 | func (fake *FinderClient) FindReleaseCallCount() int { 50 | fake.findReleaseMutex.RLock() 51 | defer fake.findReleaseMutex.RUnlock() 52 | return len(fake.findReleaseArgsForCall) 53 | } 54 | 55 | func (fake *FinderClient) FindReleaseCalls(stub func(string, int) (pivnet.Release, error)) { 56 | fake.findReleaseMutex.Lock() 57 | defer fake.findReleaseMutex.Unlock() 58 | fake.FindReleaseStub = stub 59 | } 60 | 61 | func (fake *FinderClient) FindReleaseArgsForCall(i int) (string, int) { 62 | fake.findReleaseMutex.RLock() 63 | defer fake.findReleaseMutex.RUnlock() 64 | argsForCall := fake.findReleaseArgsForCall[i] 65 | return argsForCall.arg1, argsForCall.arg2 66 | } 67 | 68 | func (fake *FinderClient) FindReleaseReturns(result1 pivnet.Release, result2 error) { 69 | fake.findReleaseMutex.Lock() 70 | defer fake.findReleaseMutex.Unlock() 71 | fake.FindReleaseStub = nil 72 | fake.findReleaseReturns = struct { 73 | result1 pivnet.Release 74 | result2 error 75 | }{result1, result2} 76 | } 77 | 78 | func (fake *FinderClient) FindReleaseReturnsOnCall(i int, result1 pivnet.Release, result2 error) { 79 | fake.findReleaseMutex.Lock() 80 | defer fake.findReleaseMutex.Unlock() 81 | fake.FindReleaseStub = nil 82 | if fake.findReleaseReturnsOnCall == nil { 83 | fake.findReleaseReturnsOnCall = make(map[int]struct { 84 | result1 pivnet.Release 85 | result2 error 86 | }) 87 | } 88 | fake.findReleaseReturnsOnCall[i] = struct { 89 | result1 pivnet.Release 90 | result2 error 91 | }{result1, result2} 92 | } 93 | 94 | func (fake *FinderClient) Invocations() map[string][][]interface{} { 95 | fake.invocationsMutex.RLock() 96 | defer fake.invocationsMutex.RUnlock() 97 | fake.findReleaseMutex.RLock() 98 | defer fake.findReleaseMutex.RUnlock() 99 | copiedInvocations := map[string][][]interface{}{} 100 | for key, value := range fake.invocations { 101 | copiedInvocations[key] = value 102 | } 103 | return copiedInvocations 104 | } 105 | 106 | func (fake *FinderClient) recordInvocation(key string, args []interface{}) { 107 | fake.invocationsMutex.Lock() 108 | defer fake.invocationsMutex.Unlock() 109 | if fake.invocations == nil { 110 | fake.invocations = map[string][][]interface{}{} 111 | } 112 | if fake.invocations[key] == nil { 113 | fake.invocations[key] = [][]interface{}{} 114 | } 115 | fake.invocations[key] = append(fake.invocations[key], args) 116 | } 117 | -------------------------------------------------------------------------------- /out/release/releasefakes/md5summer.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type Md5Summer struct { 9 | SumFileStub func(string) (string, error) 10 | sumFileMutex sync.RWMutex 11 | sumFileArgsForCall []struct { 12 | arg1 string 13 | } 14 | sumFileReturns struct { 15 | result1 string 16 | result2 error 17 | } 18 | sumFileReturnsOnCall map[int]struct { 19 | result1 string 20 | result2 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *Md5Summer) SumFile(arg1 string) (string, error) { 27 | fake.sumFileMutex.Lock() 28 | ret, specificReturn := fake.sumFileReturnsOnCall[len(fake.sumFileArgsForCall)] 29 | fake.sumFileArgsForCall = append(fake.sumFileArgsForCall, struct { 30 | arg1 string 31 | }{arg1}) 32 | stub := fake.SumFileStub 33 | fakeReturns := fake.sumFileReturns 34 | fake.recordInvocation("SumFile", []interface{}{arg1}) 35 | fake.sumFileMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1, ret.result2 41 | } 42 | return fakeReturns.result1, fakeReturns.result2 43 | } 44 | 45 | func (fake *Md5Summer) SumFileCallCount() int { 46 | fake.sumFileMutex.RLock() 47 | defer fake.sumFileMutex.RUnlock() 48 | return len(fake.sumFileArgsForCall) 49 | } 50 | 51 | func (fake *Md5Summer) SumFileCalls(stub func(string) (string, error)) { 52 | fake.sumFileMutex.Lock() 53 | defer fake.sumFileMutex.Unlock() 54 | fake.SumFileStub = stub 55 | } 56 | 57 | func (fake *Md5Summer) SumFileArgsForCall(i int) string { 58 | fake.sumFileMutex.RLock() 59 | defer fake.sumFileMutex.RUnlock() 60 | argsForCall := fake.sumFileArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *Md5Summer) SumFileReturns(result1 string, result2 error) { 65 | fake.sumFileMutex.Lock() 66 | defer fake.sumFileMutex.Unlock() 67 | fake.SumFileStub = nil 68 | fake.sumFileReturns = struct { 69 | result1 string 70 | result2 error 71 | }{result1, result2} 72 | } 73 | 74 | func (fake *Md5Summer) SumFileReturnsOnCall(i int, result1 string, result2 error) { 75 | fake.sumFileMutex.Lock() 76 | defer fake.sumFileMutex.Unlock() 77 | fake.SumFileStub = nil 78 | if fake.sumFileReturnsOnCall == nil { 79 | fake.sumFileReturnsOnCall = make(map[int]struct { 80 | result1 string 81 | result2 error 82 | }) 83 | } 84 | fake.sumFileReturnsOnCall[i] = struct { 85 | result1 string 86 | result2 error 87 | }{result1, result2} 88 | } 89 | 90 | func (fake *Md5Summer) Invocations() map[string][][]interface{} { 91 | fake.invocationsMutex.RLock() 92 | defer fake.invocationsMutex.RUnlock() 93 | fake.sumFileMutex.RLock() 94 | defer fake.sumFileMutex.RUnlock() 95 | copiedInvocations := map[string][][]interface{}{} 96 | for key, value := range fake.invocations { 97 | copiedInvocations[key] = value 98 | } 99 | return copiedInvocations 100 | } 101 | 102 | func (fake *Md5Summer) recordInvocation(key string, args []interface{}) { 103 | fake.invocationsMutex.Lock() 104 | defer fake.invocationsMutex.Unlock() 105 | if fake.invocations == nil { 106 | fake.invocations = map[string][][]interface{}{} 107 | } 108 | if fake.invocations[key] == nil { 109 | fake.invocations[key] = [][]interface{}{} 110 | } 111 | fake.invocations[key] = append(fake.invocations[key], args) 112 | } 113 | -------------------------------------------------------------------------------- /out/release/releasefakes/sha256summer.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type Sha256Summer struct { 9 | SumFileStub func(string) (string, error) 10 | sumFileMutex sync.RWMutex 11 | sumFileArgsForCall []struct { 12 | arg1 string 13 | } 14 | sumFileReturns struct { 15 | result1 string 16 | result2 error 17 | } 18 | sumFileReturnsOnCall map[int]struct { 19 | result1 string 20 | result2 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *Sha256Summer) SumFile(arg1 string) (string, error) { 27 | fake.sumFileMutex.Lock() 28 | ret, specificReturn := fake.sumFileReturnsOnCall[len(fake.sumFileArgsForCall)] 29 | fake.sumFileArgsForCall = append(fake.sumFileArgsForCall, struct { 30 | arg1 string 31 | }{arg1}) 32 | stub := fake.SumFileStub 33 | fakeReturns := fake.sumFileReturns 34 | fake.recordInvocation("SumFile", []interface{}{arg1}) 35 | fake.sumFileMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1, ret.result2 41 | } 42 | return fakeReturns.result1, fakeReturns.result2 43 | } 44 | 45 | func (fake *Sha256Summer) SumFileCallCount() int { 46 | fake.sumFileMutex.RLock() 47 | defer fake.sumFileMutex.RUnlock() 48 | return len(fake.sumFileArgsForCall) 49 | } 50 | 51 | func (fake *Sha256Summer) SumFileCalls(stub func(string) (string, error)) { 52 | fake.sumFileMutex.Lock() 53 | defer fake.sumFileMutex.Unlock() 54 | fake.SumFileStub = stub 55 | } 56 | 57 | func (fake *Sha256Summer) SumFileArgsForCall(i int) string { 58 | fake.sumFileMutex.RLock() 59 | defer fake.sumFileMutex.RUnlock() 60 | argsForCall := fake.sumFileArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *Sha256Summer) SumFileReturns(result1 string, result2 error) { 65 | fake.sumFileMutex.Lock() 66 | defer fake.sumFileMutex.Unlock() 67 | fake.SumFileStub = nil 68 | fake.sumFileReturns = struct { 69 | result1 string 70 | result2 error 71 | }{result1, result2} 72 | } 73 | 74 | func (fake *Sha256Summer) SumFileReturnsOnCall(i int, result1 string, result2 error) { 75 | fake.sumFileMutex.Lock() 76 | defer fake.sumFileMutex.Unlock() 77 | fake.SumFileStub = nil 78 | if fake.sumFileReturnsOnCall == nil { 79 | fake.sumFileReturnsOnCall = make(map[int]struct { 80 | result1 string 81 | result2 error 82 | }) 83 | } 84 | fake.sumFileReturnsOnCall[i] = struct { 85 | result1 string 86 | result2 error 87 | }{result1, result2} 88 | } 89 | 90 | func (fake *Sha256Summer) Invocations() map[string][][]interface{} { 91 | fake.invocationsMutex.RLock() 92 | defer fake.invocationsMutex.RUnlock() 93 | fake.sumFileMutex.RLock() 94 | defer fake.sumFileMutex.RUnlock() 95 | copiedInvocations := map[string][][]interface{}{} 96 | for key, value := range fake.invocations { 97 | copiedInvocations[key] = value 98 | } 99 | return copiedInvocations 100 | } 101 | 102 | func (fake *Sha256Summer) recordInvocation(key string, args []interface{}) { 103 | fake.invocationsMutex.Lock() 104 | defer fake.invocationsMutex.Unlock() 105 | if fake.invocations == nil { 106 | fake.invocations = map[string][][]interface{}{} 107 | } 108 | if fake.invocations[key] == nil { 109 | fake.invocations[key] = [][]interface{}{} 110 | } 111 | fake.invocations[key] = append(fake.invocations[key], args) 112 | } 113 | -------------------------------------------------------------------------------- /out/release/releasefakes/update_client.go: -------------------------------------------------------------------------------- 1 | // This file was generated by counterfeiter 2 | package releasefakes 3 | 4 | import ( 5 | "sync" 6 | 7 | go_pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | ) 9 | 10 | type UpdateClient struct { 11 | GetReleaseStub func(productSlug string, releaseVersion string) (go_pivnet.Release, error) 12 | getReleaseMutex sync.RWMutex 13 | getReleaseArgsForCall []struct { 14 | productSlug string 15 | releaseVersion string 16 | } 17 | getReleaseReturns struct { 18 | result1 go_pivnet.Release 19 | result2 error 20 | } 21 | invocations map[string][][]interface{} 22 | invocationsMutex sync.RWMutex 23 | } 24 | 25 | func (fake *UpdateClient) GetRelease(productSlug string, releaseVersion string) (go_pivnet.Release, error) { 26 | fake.getReleaseMutex.Lock() 27 | fake.getReleaseArgsForCall = append(fake.getReleaseArgsForCall, struct { 28 | productSlug string 29 | releaseVersion string 30 | }{productSlug, releaseVersion}) 31 | fake.recordInvocation("GetRelease", []interface{}{productSlug, releaseVersion}) 32 | fake.getReleaseMutex.Unlock() 33 | if fake.GetReleaseStub != nil { 34 | return fake.GetReleaseStub(productSlug, releaseVersion) 35 | } else { 36 | return fake.getReleaseReturns.result1, fake.getReleaseReturns.result2 37 | } 38 | } 39 | 40 | func (fake *UpdateClient) GetReleaseCallCount() int { 41 | fake.getReleaseMutex.RLock() 42 | defer fake.getReleaseMutex.RUnlock() 43 | return len(fake.getReleaseArgsForCall) 44 | } 45 | 46 | func (fake *UpdateClient) GetReleaseArgsForCall(i int) (string, string) { 47 | fake.getReleaseMutex.RLock() 48 | defer fake.getReleaseMutex.RUnlock() 49 | return fake.getReleaseArgsForCall[i].productSlug, fake.getReleaseArgsForCall[i].releaseVersion 50 | } 51 | 52 | func (fake *UpdateClient) GetReleaseReturns(result1 go_pivnet.Release, result2 error) { 53 | fake.GetReleaseStub = nil 54 | fake.getReleaseReturns = struct { 55 | result1 go_pivnet.Release 56 | result2 error 57 | }{result1, result2} 58 | } 59 | 60 | func (fake *UpdateClient) Invocations() map[string][][]interface{} { 61 | fake.invocationsMutex.RLock() 62 | defer fake.invocationsMutex.RUnlock() 63 | fake.getReleaseMutex.RLock() 64 | defer fake.getReleaseMutex.RUnlock() 65 | return fake.invocations 66 | } 67 | 68 | func (fake *UpdateClient) recordInvocation(key string, args []interface{}) { 69 | fake.invocationsMutex.Lock() 70 | defer fake.invocationsMutex.Unlock() 71 | if fake.invocations == nil { 72 | fake.invocations = map[string][][]interface{}{} 73 | } 74 | if fake.invocations[key] == nil { 75 | fake.invocations[key] = [][]interface{}{} 76 | } 77 | fake.invocations[key] = append(fake.invocations[key], args) 78 | } 79 | -------------------------------------------------------------------------------- /out/release/upgrade_path_specifiers.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | 6 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 9 | ) 10 | 11 | type UpgradePathSpecifiersCreator struct { 12 | logger logger.Logger 13 | pivnet upgradePathSpecifiersCreatorClient 14 | metadata metadata.Metadata 15 | productSlug string 16 | } 17 | 18 | func NewUpgradePathSpecifiersCreator( 19 | logger logger.Logger, 20 | pivnetClient upgradePathSpecifiersCreatorClient, 21 | metadata metadata.Metadata, 22 | productSlug string, 23 | ) UpgradePathSpecifiersCreator { 24 | return UpgradePathSpecifiersCreator{ 25 | logger: logger, 26 | pivnet: pivnetClient, 27 | metadata: metadata, 28 | productSlug: productSlug, 29 | } 30 | } 31 | 32 | //counterfeiter:generate --fake-name UpgradePathSpecifiersCreatorClient . upgradePathSpecifiersCreatorClient 33 | type upgradePathSpecifiersCreatorClient interface { 34 | CreateUpgradePathSpecifier(productSlug string, releaseID int, specifier string) (pivnet.UpgradePathSpecifier, error) 35 | } 36 | 37 | func (creator UpgradePathSpecifiersCreator) CreateUpgradePathSpecifiers(release pivnet.Release) error { 38 | for _, specifier := range creator.metadata.UpgradePathSpecifiers { 39 | creator.logger.Info(fmt.Sprintf( 40 | "Creating upgrade path specifier '%s'", 41 | specifier.Specifier, 42 | )) 43 | _, err := creator.pivnet.CreateUpgradePathSpecifier(creator.productSlug, release.ID, specifier.Specifier) 44 | if err != nil { 45 | return err 46 | } 47 | } 48 | 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /out/release/upgrade_path_specifiers_test.go: -------------------------------------------------------------------------------- 1 | package release_test 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/pivotal-cf/go-pivnet/v7" 8 | "github.com/pivotal-cf/go-pivnet/v7/logger" 9 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 10 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 11 | "github.com/pivotal-cf/pivnet-resource/v3/out/release" 12 | "github.com/pivotal-cf/pivnet-resource/v3/out/release/releasefakes" 13 | 14 | . "github.com/onsi/ginkgo" 15 | . "github.com/onsi/gomega" 16 | ) 17 | 18 | var _ = Describe("UpgradePathSpecifiersCreator", func() { 19 | Describe("CreateUpgradePathSpecifiers", func() { 20 | var ( 21 | fakeLogger logger.Logger 22 | 23 | pivnetClient *releasefakes.UpgradePathSpecifiersCreatorClient 24 | 25 | mdata metadata.Metadata 26 | 27 | productSlug string 28 | pivnetRelease pivnet.Release 29 | 30 | upgradePathSpecifiersCreator release.UpgradePathSpecifiersCreator 31 | ) 32 | 33 | BeforeEach(func() { 34 | logger := log.New(GinkgoWriter, "", log.LstdFlags) 35 | fakeLogger = logshim.NewLogShim(logger, logger, true) 36 | 37 | pivnetClient = &releasefakes.UpgradePathSpecifiersCreatorClient{} 38 | 39 | productSlug = "some-product-slug" 40 | 41 | pivnetRelease = pivnet.Release{ 42 | Availability: "some-value", 43 | ID: 1337, 44 | Version: "some-version", 45 | EULA: &pivnet.EULA{ 46 | Slug: "a_eula_slug", 47 | }, 48 | } 49 | 50 | mdata = metadata.Metadata{ 51 | Release: &metadata.Release{ 52 | Availability: "some-value", 53 | Version: "some-version", 54 | EULASlug: "a_eula_slug", 55 | }, 56 | ProductFiles: []metadata.ProductFile{}, 57 | } 58 | 59 | pivnetClient.CreateUpgradePathSpecifierReturns(pivnet.UpgradePathSpecifier{}, nil) 60 | }) 61 | 62 | JustBeforeEach(func() { 63 | upgradePathSpecifiersCreator = release.NewUpgradePathSpecifiersCreator( 64 | fakeLogger, 65 | pivnetClient, 66 | mdata, 67 | productSlug, 68 | ) 69 | }) 70 | 71 | Context("when upgrade path specifiers are provided", func() { 72 | BeforeEach(func() { 73 | mdata.UpgradePathSpecifiers = []metadata.UpgradePathSpecifier{ 74 | { 75 | ID: 9876, 76 | Specifier: "1.2.*", 77 | }, 78 | { 79 | ID: 8765, 80 | Specifier: "2.3.*", 81 | }, 82 | } 83 | }) 84 | 85 | It("creates the upgrade paths", func() { 86 | err := upgradePathSpecifiersCreator.CreateUpgradePathSpecifiers(pivnetRelease) 87 | Expect(err).NotTo(HaveOccurred()) 88 | 89 | Expect(pivnetClient.CreateUpgradePathSpecifierCallCount()).To(Equal(2)) 90 | }) 91 | 92 | Context("when creating upgrade path specifier returns an error ", func() { 93 | var ( 94 | expectedErr error 95 | ) 96 | 97 | BeforeEach(func() { 98 | expectedErr = fmt.Errorf("boom") 99 | pivnetClient.CreateUpgradePathSpecifierReturns(pivnet.UpgradePathSpecifier{}, expectedErr) 100 | }) 101 | 102 | It("returns an error", func() { 103 | err := upgradePathSpecifiersCreator.CreateUpgradePathSpecifiers(pivnetRelease) 104 | Expect(err).To(HaveOccurred()) 105 | 106 | Expect(err).To(Equal(expectedErr)) 107 | }) 108 | }) 109 | }) 110 | }) 111 | }) 112 | -------------------------------------------------------------------------------- /out/release/upgrade_paths.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | 6 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 7 | "github.com/pivotal-cf/go-pivnet/v7/logger" 8 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 9 | ) 10 | 11 | type ReleaseUpgradePathsAdder struct { 12 | logger logger.Logger 13 | pivnet releaseUpgradePathsAdderClient 14 | metadata metadata.Metadata 15 | productSlug string 16 | filter filter 17 | } 18 | 19 | func NewReleaseUpgradePathsAdder( 20 | logger logger.Logger, 21 | pivnetClient releaseUpgradePathsAdderClient, 22 | metadata metadata.Metadata, 23 | productSlug string, 24 | filter filter, 25 | ) ReleaseUpgradePathsAdder { 26 | return ReleaseUpgradePathsAdder{ 27 | logger: logger, 28 | pivnet: pivnetClient, 29 | metadata: metadata, 30 | productSlug: productSlug, 31 | filter: filter, 32 | } 33 | } 34 | 35 | //counterfeiter:generate --fake-name ReleaseUpgradePathsAdderClient . releaseUpgradePathsAdderClient 36 | type releaseUpgradePathsAdderClient interface { 37 | AddReleaseUpgradePath(productSlug string, releaseID int, previousReleaseID int) error 38 | ReleasesForProductSlug(productSlug string) ([]pivnet.Release, error) 39 | } 40 | 41 | //counterfeiter:generate --fake-name FakeFilter . filter 42 | type filter interface { 43 | ReleasesByVersion(releases []pivnet.Release, version string) ([]pivnet.Release, error) 44 | } 45 | 46 | func (rf ReleaseUpgradePathsAdder) AddReleaseUpgradePaths(release pivnet.Release) error { 47 | allReleases, err := rf.pivnet.ReleasesForProductSlug(rf.productSlug) 48 | if err != nil { 49 | return err 50 | } 51 | 52 | upgradeFromReleases := map[pivnet.Release]interface{}{} 53 | 54 | for i, u := range rf.metadata.UpgradePaths { 55 | if u.ID == 0 && u.Version == "" { 56 | return fmt.Errorf( 57 | "Either id or version must be provided for upgrade_paths[%d]", 58 | i, 59 | ) 60 | } 61 | 62 | if u.ID == 0 { 63 | matchingReleases, err := rf.filter.ReleasesByVersion(allReleases, u.Version) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | if len(matchingReleases) == 0 { 69 | return fmt.Errorf("No releases found for version: '%s'", u.Version) 70 | } 71 | 72 | for _, r := range matchingReleases { 73 | upgradeFromReleases[r] = nil 74 | } 75 | } else { 76 | r, err := filterReleasesForID(allReleases, u.ID) 77 | if err != nil { 78 | return err 79 | } 80 | 81 | upgradeFromReleases[r] = nil 82 | } 83 | } 84 | 85 | for r, _ := range upgradeFromReleases { 86 | rf.logger.Info(fmt.Sprintf( 87 | "Adding upgrade path: '%s'", 88 | r.Version, 89 | )) 90 | 91 | if r.ID == release.ID { 92 | rf.logger.Info(fmt.Sprintf("skipping release: %s", r.Version)) 93 | continue 94 | } 95 | 96 | err := rf.pivnet.AddReleaseUpgradePath(rf.productSlug, release.ID, r.ID) 97 | if err != nil { 98 | return err 99 | } 100 | } 101 | 102 | return nil 103 | } 104 | 105 | func filterReleasesForID(releases []pivnet.Release, id int) (pivnet.Release, error) { 106 | for _, r := range releases { 107 | if r.ID == id { 108 | return r, nil 109 | } 110 | } 111 | 112 | return pivnet.Release{}, fmt.Errorf("No releases found for id: '%d'", id) 113 | } 114 | -------------------------------------------------------------------------------- /out/release/user_groups.go: -------------------------------------------------------------------------------- 1 | package release 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | pivnet "github.com/pivotal-cf/go-pivnet/v7" 8 | "github.com/pivotal-cf/go-pivnet/v7/logger" 9 | "github.com/pivotal-cf/pivnet-resource/v3/metadata" 10 | ) 11 | 12 | type UserGroupsUpdater struct { 13 | logger logger.Logger 14 | pivnet userGroupsUpdaterClient 15 | metadata metadata.Metadata 16 | productSlug string 17 | } 18 | 19 | func NewUserGroupsUpdater( 20 | logger logger.Logger, 21 | pivnetClient userGroupsUpdaterClient, 22 | metadata metadata.Metadata, 23 | productSlug string, 24 | ) UserGroupsUpdater { 25 | return UserGroupsUpdater{ 26 | logger: logger, 27 | pivnet: pivnetClient, 28 | metadata: metadata, 29 | productSlug: productSlug, 30 | } 31 | } 32 | 33 | //counterfeiter:generate --fake-name UserGroupsUpdaterClient . userGroupsUpdaterClient 34 | type userGroupsUpdaterClient interface { 35 | UpdateRelease(productSlug string, release pivnet.Release) (pivnet.Release, error) 36 | AddUserGroup(productSlug string, releaseID int, userGroupID int) error 37 | } 38 | 39 | func (rf UserGroupsUpdater) UpdateUserGroups(release pivnet.Release) (pivnet.Release, error) { 40 | 41 | availability := rf.metadata.Release.Availability 42 | 43 | if availability != "Admins Only" { 44 | releaseUpdate := pivnet.Release{ 45 | ID: release.ID, 46 | Availability: availability, 47 | } 48 | 49 | rf.logger.Info(fmt.Sprintf( 50 | "Updating availability to: '%s'", 51 | availability, 52 | )) 53 | 54 | var err error 55 | release, err = rf.pivnet.UpdateRelease(rf.productSlug, releaseUpdate) 56 | if err != nil { 57 | return pivnet.Release{}, err 58 | } 59 | 60 | if availability == "Selected User Groups Only" { 61 | userGroupIDs := rf.metadata.Release.UserGroupIDs 62 | 63 | for _, userGroupIDString := range userGroupIDs { 64 | userGroupID, err := strconv.Atoi(userGroupIDString) 65 | if err != nil { 66 | return pivnet.Release{}, err 67 | } 68 | 69 | rf.logger.Info(fmt.Sprintf( 70 | "Adding user group with ID: %d", 71 | userGroupID, 72 | )) 73 | err = rf.pivnet.AddUserGroup(rf.productSlug, release.ID, userGroupID) 74 | if err != nil { 75 | return pivnet.Release{}, err 76 | } 77 | } 78 | } 79 | } 80 | 81 | return release, nil 82 | } 83 | -------------------------------------------------------------------------------- /s3/package.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /s3/s3_client.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/concourse/s3-resource" 11 | "github.com/pivotal-cf/go-pivnet/v7/logger" 12 | ) 13 | 14 | //counterfeiter:generate --fake-name FakeFileSizeGetter . fileSizeGetter 15 | type fileSizeGetter interface { 16 | FileSize(localPath string) (int64, error) 17 | } 18 | 19 | type FileSizeGetter struct{} 20 | 21 | func (f FileSizeGetter) FileSize(localPath string) (int64, error) { 22 | fileInfo, err := os.Lstat(localPath) 23 | if err != nil { 24 | return 0, err 25 | } 26 | 27 | return fileInfo.Size(), nil 28 | } 29 | 30 | type Client struct { 31 | bucket string 32 | 33 | logger logger.Logger 34 | stderr io.Writer 35 | 36 | s3client s3resource.S3Client 37 | fileSizeGetter fileSizeGetter 38 | } 39 | 40 | type NewClientConfig struct { 41 | AccessKeyID string 42 | SecretAccessKey string 43 | SessionToken string 44 | RegionName string 45 | Bucket string 46 | 47 | Logger logger.Logger 48 | Stderr io.Writer 49 | SkipSSLValidation bool 50 | FileSizeGetter fileSizeGetter 51 | } 52 | 53 | func NewClient(config NewClientConfig) *Client { 54 | endpoint := "" 55 | disableSSL := config.SkipSSLValidation 56 | 57 | awsConfig := s3resource.NewAwsConfig( 58 | config.AccessKeyID, 59 | config.SecretAccessKey, 60 | config.SessionToken, 61 | config.RegionName, 62 | endpoint, 63 | disableSSL, 64 | config.SkipSSLValidation, 65 | ) 66 | 67 | s3client := s3resource.NewS3Client( 68 | config.Stderr, 69 | awsConfig, 70 | false, 71 | ) 72 | 73 | return &Client{ 74 | bucket: config.Bucket, 75 | stderr: config.Stderr, 76 | logger: config.Logger, 77 | s3client: s3client, 78 | fileSizeGetter: config.FileSizeGetter, 79 | } 80 | } 81 | 82 | func (c Client) Upload(fileGlob string, to string, sourcesDir string) error { 83 | matches, err := filepath.Glob(filepath.Join(sourcesDir, fileGlob)) 84 | 85 | if err != nil { 86 | return err 87 | } 88 | 89 | if len(matches) == 0 { 90 | return fmt.Errorf("no matches found for pattern: '%s'", fileGlob) 91 | } 92 | 93 | if len(matches) > 1 { 94 | return fmt.Errorf( 95 | "more than one match found for pattern: '%s': %v", 96 | fileGlob, 97 | matches, 98 | ) 99 | } 100 | 101 | localPath := matches[0] 102 | 103 | fileSize, err := c.fileSizeGetter.FileSize(localPath) 104 | if err != nil { 105 | return err 106 | } 107 | 108 | if fileSize > 20000000000 { 109 | return errors.New("file size exceeds 20 gb limit") 110 | } 111 | 112 | remotePath := filepath.Join(to, filepath.Base(localPath)) 113 | 114 | options := s3resource.NewUploadFileOptions() 115 | 116 | c.logger.Info(fmt.Sprintf( 117 | "Uploading %s to s3://%s/%s", 118 | localPath, 119 | c.bucket, 120 | remotePath, 121 | )) 122 | 123 | _, err = c.s3client.UploadFile( 124 | c.bucket, 125 | remotePath, 126 | localPath, 127 | options, 128 | ) 129 | if err != nil { 130 | return err 131 | } 132 | 133 | // the s3client does not append a new-line to its output 134 | fmt.Fprintln(c.stderr) 135 | 136 | c.logger.Info(fmt.Sprintf( 137 | "Successfully uploaded '%s' to 's3://%s/%s'", 138 | localPath, 139 | c.bucket, 140 | remotePath, 141 | )) 142 | 143 | return nil 144 | } 145 | -------------------------------------------------------------------------------- /s3/s3_client_test.go: -------------------------------------------------------------------------------- 1 | package s3_test 2 | 3 | import ( 4 | "github.com/pivotal-cf/pivnet-resource/v3/s3/s3fakes" 5 | "io/ioutil" 6 | "os" 7 | "path/filepath" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | "github.com/pivotal-cf/pivnet-resource/v3/s3" 12 | ) 13 | 14 | var _ = Describe("S3 Client", func() { 15 | var ( 16 | client *s3.Client 17 | fakeFileSizeGetter *s3fakes.FakeFileSizeGetter 18 | ) 19 | 20 | BeforeEach(func() { 21 | fakeFileSizeGetter = &s3fakes.FakeFileSizeGetter{} 22 | client = s3.NewClient(s3.NewClientConfig{FileSizeGetter: fakeFileSizeGetter}) 23 | }) 24 | 25 | Describe("Upload file", func() { 26 | var ( 27 | sourcesDir string 28 | fileGlob string 29 | to string 30 | ) 31 | 32 | BeforeEach(func() { 33 | fileGlob = "some-file*" 34 | to = "some-remote-file-name" 35 | 36 | var err error 37 | sourcesDir, err = ioutil.TempDir("", "pivnet-resource-s3-test") 38 | Expect(err).ShouldNot(HaveOccurred()) 39 | 40 | err = ioutil.WriteFile( 41 | filepath.Join(sourcesDir, fileGlob), 42 | nil, 43 | os.ModePerm, 44 | ) 45 | Expect(err).ShouldNot(HaveOccurred()) 46 | }) 47 | 48 | AfterEach(func() { 49 | By("Removing local temp files") 50 | err := os.RemoveAll(sourcesDir) 51 | Expect(err).ShouldNot(HaveOccurred()) 52 | }) 53 | 54 | Context("when glob is badly-formed", func() { 55 | BeforeEach(func() { 56 | fileGlob = "[" 57 | }) 58 | 59 | It("returns error", func() { 60 | err := client.Upload(fileGlob, to, sourcesDir) 61 | Expect(err).To(HaveOccurred()) 62 | }) 63 | }) 64 | 65 | Context("when glob does not match anything", func() { 66 | BeforeEach(func() { 67 | fileGlob = "this-will-not-match" 68 | }) 69 | 70 | It("returns error", func() { 71 | err := client.Upload(fileGlob, to, sourcesDir) 72 | Expect(err).To(HaveOccurred()) 73 | }) 74 | }) 75 | 76 | Context("when glob matches more than one file", func() { 77 | BeforeEach(func() { 78 | err := ioutil.WriteFile( 79 | filepath.Join(sourcesDir, "some-file-2"), 80 | nil, 81 | os.ModePerm, 82 | ) 83 | Expect(err).ShouldNot(HaveOccurred()) 84 | }) 85 | 86 | It("returns error", func() { 87 | err := client.Upload(fileGlob, to, sourcesDir) 88 | Expect(err).To(HaveOccurred()) 89 | }) 90 | }) 91 | 92 | Context("when file size is greater than 20gb", func() { 93 | BeforeEach(func() { 94 | fakeFileSizeGetter.FileSizeReturns(25000000000, nil) 95 | }) 96 | It("returns error", func() { 97 | err := client.Upload(fileGlob, to, sourcesDir) 98 | Expect(err).To(HaveOccurred()) 99 | }) 100 | }) 101 | }) 102 | }) 103 | -------------------------------------------------------------------------------- /s3/s3_suite_test.go: -------------------------------------------------------------------------------- 1 | package s3_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestOut(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "S3 Suite") 13 | } 14 | -------------------------------------------------------------------------------- /s3/s3fakes/fake_file_size_getter.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package s3fakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type FakeFileSizeGetter struct { 9 | FileSizeStub func(string) (int64, error) 10 | fileSizeMutex sync.RWMutex 11 | fileSizeArgsForCall []struct { 12 | arg1 string 13 | } 14 | fileSizeReturns struct { 15 | result1 int64 16 | result2 error 17 | } 18 | fileSizeReturnsOnCall map[int]struct { 19 | result1 int64 20 | result2 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *FakeFileSizeGetter) FileSize(arg1 string) (int64, error) { 27 | fake.fileSizeMutex.Lock() 28 | ret, specificReturn := fake.fileSizeReturnsOnCall[len(fake.fileSizeArgsForCall)] 29 | fake.fileSizeArgsForCall = append(fake.fileSizeArgsForCall, struct { 30 | arg1 string 31 | }{arg1}) 32 | stub := fake.FileSizeStub 33 | fakeReturns := fake.fileSizeReturns 34 | fake.recordInvocation("FileSize", []interface{}{arg1}) 35 | fake.fileSizeMutex.Unlock() 36 | if stub != nil { 37 | return stub(arg1) 38 | } 39 | if specificReturn { 40 | return ret.result1, ret.result2 41 | } 42 | return fakeReturns.result1, fakeReturns.result2 43 | } 44 | 45 | func (fake *FakeFileSizeGetter) FileSizeCallCount() int { 46 | fake.fileSizeMutex.RLock() 47 | defer fake.fileSizeMutex.RUnlock() 48 | return len(fake.fileSizeArgsForCall) 49 | } 50 | 51 | func (fake *FakeFileSizeGetter) FileSizeCalls(stub func(string) (int64, error)) { 52 | fake.fileSizeMutex.Lock() 53 | defer fake.fileSizeMutex.Unlock() 54 | fake.FileSizeStub = stub 55 | } 56 | 57 | func (fake *FakeFileSizeGetter) FileSizeArgsForCall(i int) string { 58 | fake.fileSizeMutex.RLock() 59 | defer fake.fileSizeMutex.RUnlock() 60 | argsForCall := fake.fileSizeArgsForCall[i] 61 | return argsForCall.arg1 62 | } 63 | 64 | func (fake *FakeFileSizeGetter) FileSizeReturns(result1 int64, result2 error) { 65 | fake.fileSizeMutex.Lock() 66 | defer fake.fileSizeMutex.Unlock() 67 | fake.FileSizeStub = nil 68 | fake.fileSizeReturns = struct { 69 | result1 int64 70 | result2 error 71 | }{result1, result2} 72 | } 73 | 74 | func (fake *FakeFileSizeGetter) FileSizeReturnsOnCall(i int, result1 int64, result2 error) { 75 | fake.fileSizeMutex.Lock() 76 | defer fake.fileSizeMutex.Unlock() 77 | fake.FileSizeStub = nil 78 | if fake.fileSizeReturnsOnCall == nil { 79 | fake.fileSizeReturnsOnCall = make(map[int]struct { 80 | result1 int64 81 | result2 error 82 | }) 83 | } 84 | fake.fileSizeReturnsOnCall[i] = struct { 85 | result1 int64 86 | result2 error 87 | }{result1, result2} 88 | } 89 | 90 | func (fake *FakeFileSizeGetter) Invocations() map[string][][]interface{} { 91 | fake.invocationsMutex.RLock() 92 | defer fake.invocationsMutex.RUnlock() 93 | fake.fileSizeMutex.RLock() 94 | defer fake.fileSizeMutex.RUnlock() 95 | copiedInvocations := map[string][][]interface{}{} 96 | for key, value := range fake.invocations { 97 | copiedInvocations[key] = value 98 | } 99 | return copiedInvocations 100 | } 101 | 102 | func (fake *FakeFileSizeGetter) recordInvocation(key string, args []interface{}) { 103 | fake.invocationsMutex.Lock() 104 | defer fake.invocationsMutex.Unlock() 105 | if fake.invocations == nil { 106 | fake.invocations = map[string][][]interface{}{} 107 | } 108 | if fake.invocations[key] == nil { 109 | fake.invocations[key] = [][]interface{}{} 110 | } 111 | fake.invocations[key] = append(fake.invocations[key], args) 112 | } 113 | -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | VERSION="${VERSION:-dev}" 6 | GOOS="${GOOS:-linux}" 7 | 8 | my_dir="$( cd "$( dirname "${0}" )" && pwd )" 9 | base_dir="$( cd "${my_dir}/.." && pwd )" 10 | 11 | pushd "${base_dir}" > /dev/null 12 | GO111MODULE=on go mod vendor 13 | GOOS="${GOOS}" go build \ 14 | -o "${base_dir}/cmd/check/check" \ 15 | -ldflags "-X main.version=${VERSION}" \ 16 | ./cmd/check 17 | GOOS="${GOOS}" go build \ 18 | -o "${base_dir}/cmd/in/in" \ 19 | -ldflags "-X main.version=${VERSION}" \ 20 | ./cmd/in 21 | GOOS="${GOOS}" go build \ 22 | -o "${base_dir}/cmd/out/out" \ 23 | -ldflags "-X main.version=${VERSION}" \ 24 | ./cmd/out 25 | popd > /dev/null 26 | -------------------------------------------------------------------------------- /semver/semver.go: -------------------------------------------------------------------------------- 1 | package semver 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/blang/semver" 8 | "github.com/pivotal-cf/go-pivnet/v7/logger" 9 | ) 10 | 11 | type SemverConverter struct { 12 | logger logger.Logger 13 | } 14 | 15 | func NewSemverConverter(logger logger.Logger) *SemverConverter { 16 | return &SemverConverter{logger} 17 | } 18 | 19 | // ToValidSemver attempts to return the input as valid semver. 20 | // If the input fails to parse as semver, it appends .0 or .0.0 to the input and retries 21 | // If this is still not valid semver, it returns an error 22 | func (s SemverConverter) ToValidSemver(input string) (semver.Version, error) { 23 | v, err := semver.Parse(input) 24 | if err == nil { 25 | return v, nil 26 | } 27 | 28 | s.logger.Info(fmt.Sprintf( 29 | "failed to parse semver: '%s', appending zeros and trying again", 30 | input, 31 | )) 32 | maybeSemver := input 33 | 34 | segs := strings.SplitN(maybeSemver, ".", 3) 35 | switch len(segs) { 36 | case 2: 37 | maybeSemver += ".0" 38 | case 1: 39 | maybeSemver += ".0.0" 40 | } 41 | 42 | v, err = semver.Parse(maybeSemver) 43 | if err == nil { 44 | return v, nil 45 | } 46 | 47 | s.logger.Info(fmt.Sprintf( 48 | "still failed to parse semver: '%s', giving up", 49 | maybeSemver, 50 | )) 51 | 52 | return semver.Version{}, err 53 | } 54 | -------------------------------------------------------------------------------- /semver/semver_suite_test.go: -------------------------------------------------------------------------------- 1 | package semver 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestSorter(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Semver Suite") 13 | } 14 | -------------------------------------------------------------------------------- /semver/semver_test.go: -------------------------------------------------------------------------------- 1 | package semver_test 2 | 3 | import ( 4 | "log" 5 | 6 | bsemver "github.com/blang/semver" 7 | "github.com/pivotal-cf/go-pivnet/v7/logshim" 8 | "github.com/pivotal-cf/pivnet-resource/v3/semver" 9 | 10 | . "github.com/onsi/ginkgo" 11 | . "github.com/onsi/gomega" 12 | ) 13 | 14 | var _ = Describe("SemverConverter", func() { 15 | var ( 16 | s *semver.SemverConverter 17 | ) 18 | 19 | BeforeEach(func() { 20 | logger := log.New(GinkgoWriter, "", log.LstdFlags) 21 | fakeLogger := logshim.NewLogShim(logger, logger, true) 22 | s = semver.NewSemverConverter(fakeLogger) 23 | }) 24 | 25 | Describe("ToValidSemver", func() { 26 | var ( 27 | input string 28 | ) 29 | 30 | BeforeEach(func() { 31 | input = "1.2.3-edge.12" 32 | }) 33 | 34 | It("parses valid semver", func() { 35 | returned, err := s.ToValidSemver(input) 36 | Expect(err).NotTo(HaveOccurred()) 37 | 38 | expectedReturned := bsemver.Version{ 39 | Major: 1, 40 | Minor: 2, 41 | Patch: 3, 42 | Pre: []bsemver.PRVersion{ 43 | {VersionStr: "edge"}, 44 | {VersionNum: 12, IsNum: true}, 45 | }, 46 | } 47 | Expect(returned).To(Equal(expectedReturned)) 48 | }) 49 | 50 | Context("when parsing a version as semver fails", func() { 51 | BeforeEach(func() { 52 | input = "invalid-semver" 53 | }) 54 | 55 | It("returns error", func() { 56 | _, err := s.ToValidSemver(input) 57 | Expect(err).To(HaveOccurred()) 58 | }) 59 | }) 60 | 61 | Context("when the input has one component", func() { 62 | BeforeEach(func() { 63 | input = "1" 64 | }) 65 | 66 | It("returns with 3 components (adds zeros) without error", func() { 67 | returned, err := s.ToValidSemver(input) 68 | Expect(err).NotTo(HaveOccurred()) 69 | 70 | expectedReturned := bsemver.Version{ 71 | Major: 1, 72 | Minor: 0, 73 | Patch: 0, 74 | } 75 | Expect(returned).To(Equal(expectedReturned)) 76 | }) 77 | }) 78 | 79 | Context("when the input has two components", func() { 80 | BeforeEach(func() { 81 | input = "1.2" 82 | }) 83 | 84 | It("returns with 3 components (adds zeros) without error", func() { 85 | returned, err := s.ToValidSemver(input) 86 | Expect(err).NotTo(HaveOccurred()) 87 | 88 | expectedReturned := bsemver.Version{ 89 | Major: 1, 90 | Minor: 2, 91 | Patch: 0, 92 | } 93 | Expect(returned).To(Equal(expectedReturned)) 94 | }) 95 | }) 96 | 97 | Context("when a version has more than 3 components", func() { 98 | BeforeEach(func() { 99 | input = "1.2.3.4" 100 | }) 101 | 102 | It("returns error", func() { 103 | _, err := s.ToValidSemver(input) 104 | Expect(err).To(HaveOccurred()) 105 | }) 106 | }) 107 | }) 108 | }) 109 | -------------------------------------------------------------------------------- /sorter/package.go: -------------------------------------------------------------------------------- 1 | package sorter 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /sorter/sorter.go: -------------------------------------------------------------------------------- 1 | package sorter 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "time" 7 | 8 | "github.com/blang/semver" 9 | "github.com/pivotal-cf/go-pivnet/v7" 10 | "github.com/pivotal-cf/go-pivnet/v7/logger" 11 | ) 12 | 13 | //counterfeiter:generate --fake-name FakeSemverConverter . semverConverter 14 | type semverConverter interface { 15 | ToValidSemver(string) (semver.Version, error) 16 | } 17 | 18 | type Sorter struct { 19 | logger logger.Logger 20 | semverConverter semverConverter 21 | } 22 | 23 | func NewSorter(logger logger.Logger, semverConverter semverConverter) *Sorter { 24 | return &Sorter{ 25 | logger: logger, 26 | semverConverter: semverConverter, 27 | } 28 | } 29 | 30 | // SortBySemver returns the provided releases, ordered by semantic versioning, 31 | // in descending order i.e. [4.2.3, 1.2.1, 1.2.0] 32 | // If a version cannot be parsed as semantic versioning, this is logged to stdout 33 | // and that release is not returned. No error is returned in this case. 34 | // Therefore the number of returned releases may be fewer than the number of 35 | // provided releases. 36 | func (s Sorter) SortBySemver(input []pivnet.Release) ([]pivnet.Release, error) { 37 | var versions []semver.Version 38 | versionsToReleases := make(map[string]pivnet.Release) 39 | 40 | for _, release := range input { 41 | asSemver, err := s.semverConverter.ToValidSemver(release.Version) 42 | if err != nil { 43 | s.logger.Info(fmt.Sprintf( 44 | "failed to parse release version as semver: '%s'", 45 | release.Version, 46 | )) 47 | continue 48 | } 49 | 50 | versionsToReleases[asSemver.String()] = release 51 | versions = append(versions, asSemver) 52 | } 53 | 54 | semver.Sort(versions) 55 | 56 | sortedStrings := toStrings(versions) 57 | 58 | sortedReleases := make([]pivnet.Release, len(sortedStrings)) 59 | 60 | count := len(sortedStrings) 61 | for i, v := range sortedStrings { 62 | // perform reversal so we return descending, not ascending 63 | sortedReleases[count-i-1] = versionsToReleases[v] 64 | } 65 | 66 | return sortedReleases, nil 67 | } 68 | 69 | func (s Sorter) SortByLastUpdated(input []pivnet.Release) ([]pivnet.Release, error) { 70 | releasesMap := make(map[int64][]pivnet.Release) 71 | 72 | for _, release := range input { 73 | t, err := getMostRecentTimestampFromRelease(release) 74 | if err != nil { 75 | return nil, err 76 | } 77 | 78 | releasesMap[t] = append(releasesMap[t], release) 79 | } 80 | 81 | return sortReleasesByTimestamp(releasesMap), nil 82 | } 83 | 84 | func toStrings(input semver.Versions) []string { 85 | strings := make([]string, len(input)) 86 | 87 | for i, v := range input { 88 | strings[i] = v.String() 89 | } 90 | 91 | return strings 92 | } 93 | 94 | func getMostRecentTimestampFromRelease(release pivnet.Release) (int64, error) { 95 | updatedAtTimestamp, err := time.Parse(time.RFC3339, release.UpdatedAt) 96 | if err != nil { 97 | return 0, err 98 | } 99 | 100 | mostRecentTimestamp := updatedAtTimestamp.Unix() 101 | 102 | if release.UserGroupsUpdatedAt != "" { 103 | userGroupUpdatedAtTimestamp, err := time.Parse(time.RFC3339, release.UserGroupsUpdatedAt) 104 | if err != nil { 105 | return 0, err 106 | } 107 | 108 | if mostRecentTimestamp < userGroupUpdatedAtTimestamp.Unix() { 109 | mostRecentTimestamp = userGroupUpdatedAtTimestamp.Unix() 110 | } 111 | } 112 | 113 | return mostRecentTimestamp, nil 114 | } 115 | 116 | func sortReleasesByTimestamp(releasesMap map[int64][]pivnet.Release) (result []pivnet.Release) { 117 | var keys []int64 118 | 119 | for key := range releasesMap { 120 | keys = append(keys, key) 121 | } 122 | 123 | sort.Slice(keys, func(i, j int) bool { 124 | return keys[i] > keys[j] 125 | }) 126 | 127 | for _, key := range keys { 128 | result = append(result, releasesMap[key]...) 129 | } 130 | 131 | return result 132 | } 133 | -------------------------------------------------------------------------------- /sorter/sorter_suite_test.go: -------------------------------------------------------------------------------- 1 | package sorter_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestSorter(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Sorter Suite") 13 | } 14 | -------------------------------------------------------------------------------- /sorter/sorterfakes/fake_semver_converter.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package sorterfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | "github.com/blang/semver" 8 | ) 9 | 10 | type FakeSemverConverter struct { 11 | ToValidSemverStub func(string) (semver.Version, error) 12 | toValidSemverMutex sync.RWMutex 13 | toValidSemverArgsForCall []struct { 14 | arg1 string 15 | } 16 | toValidSemverReturns struct { 17 | result1 semver.Version 18 | result2 error 19 | } 20 | toValidSemverReturnsOnCall map[int]struct { 21 | result1 semver.Version 22 | result2 error 23 | } 24 | invocations map[string][][]interface{} 25 | invocationsMutex sync.RWMutex 26 | } 27 | 28 | func (fake *FakeSemverConverter) ToValidSemver(arg1 string) (semver.Version, error) { 29 | fake.toValidSemverMutex.Lock() 30 | ret, specificReturn := fake.toValidSemverReturnsOnCall[len(fake.toValidSemverArgsForCall)] 31 | fake.toValidSemverArgsForCall = append(fake.toValidSemverArgsForCall, struct { 32 | arg1 string 33 | }{arg1}) 34 | stub := fake.ToValidSemverStub 35 | fakeReturns := fake.toValidSemverReturns 36 | fake.recordInvocation("ToValidSemver", []interface{}{arg1}) 37 | fake.toValidSemverMutex.Unlock() 38 | if stub != nil { 39 | return stub(arg1) 40 | } 41 | if specificReturn { 42 | return ret.result1, ret.result2 43 | } 44 | return fakeReturns.result1, fakeReturns.result2 45 | } 46 | 47 | func (fake *FakeSemverConverter) ToValidSemverCallCount() int { 48 | fake.toValidSemverMutex.RLock() 49 | defer fake.toValidSemverMutex.RUnlock() 50 | return len(fake.toValidSemverArgsForCall) 51 | } 52 | 53 | func (fake *FakeSemverConverter) ToValidSemverCalls(stub func(string) (semver.Version, error)) { 54 | fake.toValidSemverMutex.Lock() 55 | defer fake.toValidSemverMutex.Unlock() 56 | fake.ToValidSemverStub = stub 57 | } 58 | 59 | func (fake *FakeSemverConverter) ToValidSemverArgsForCall(i int) string { 60 | fake.toValidSemverMutex.RLock() 61 | defer fake.toValidSemverMutex.RUnlock() 62 | argsForCall := fake.toValidSemverArgsForCall[i] 63 | return argsForCall.arg1 64 | } 65 | 66 | func (fake *FakeSemverConverter) ToValidSemverReturns(result1 semver.Version, result2 error) { 67 | fake.toValidSemverMutex.Lock() 68 | defer fake.toValidSemverMutex.Unlock() 69 | fake.ToValidSemverStub = nil 70 | fake.toValidSemverReturns = struct { 71 | result1 semver.Version 72 | result2 error 73 | }{result1, result2} 74 | } 75 | 76 | func (fake *FakeSemverConverter) ToValidSemverReturnsOnCall(i int, result1 semver.Version, result2 error) { 77 | fake.toValidSemverMutex.Lock() 78 | defer fake.toValidSemverMutex.Unlock() 79 | fake.ToValidSemverStub = nil 80 | if fake.toValidSemverReturnsOnCall == nil { 81 | fake.toValidSemverReturnsOnCall = make(map[int]struct { 82 | result1 semver.Version 83 | result2 error 84 | }) 85 | } 86 | fake.toValidSemverReturnsOnCall[i] = struct { 87 | result1 semver.Version 88 | result2 error 89 | }{result1, result2} 90 | } 91 | 92 | func (fake *FakeSemverConverter) Invocations() map[string][][]interface{} { 93 | fake.invocationsMutex.RLock() 94 | defer fake.invocationsMutex.RUnlock() 95 | fake.toValidSemverMutex.RLock() 96 | defer fake.toValidSemverMutex.RUnlock() 97 | copiedInvocations := map[string][][]interface{}{} 98 | for key, value := range fake.invocations { 99 | copiedInvocations[key] = value 100 | } 101 | return copiedInvocations 102 | } 103 | 104 | func (fake *FakeSemverConverter) recordInvocation(key string, args []interface{}) { 105 | fake.invocationsMutex.Lock() 106 | defer fake.invocationsMutex.Unlock() 107 | if fake.invocations == nil { 108 | fake.invocations = map[string][][]interface{}{} 109 | } 110 | if fake.invocations[key] == nil { 111 | fake.invocations[key] = [][]interface{}{} 112 | } 113 | fake.invocations[key] = append(fake.invocations[key], args) 114 | } 115 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/maxbrunsfeld/counterfeiter/v6" 7 | ) 8 | 9 | // This file imports packages that are used when running go generate, or used 10 | // during the development process but not otherwise depended on by built code. 11 | -------------------------------------------------------------------------------- /ui/ui.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | 7 | "github.com/fatih/color" 8 | ) 9 | 10 | type UIPrinter struct { 11 | outWriter io.Writer 12 | } 13 | 14 | func NewUIPrinter(outWriter io.Writer) *UIPrinter { 15 | return &UIPrinter{ 16 | outWriter: outWriter, 17 | } 18 | } 19 | 20 | func (p *UIPrinter) PrintDeprecationln(text string) { 21 | f := color.New(color.FgYellow).SprintfFunc() 22 | text = "WARNING: " + text 23 | fmt.Fprintln(p.outWriter, f(text)) 24 | } 25 | 26 | func (p *UIPrinter) PrintErrorln(err error) { 27 | p.PrintErrorlnf("%v", err) 28 | } 29 | 30 | func (p *UIPrinter) PrintErrorlnf(text string, args ...interface{}) { 31 | f := color.New(color.FgRed).SprintfFunc() 32 | text = "ERROR: " + text 33 | fmt.Fprintln(p.outWriter, f(text, args...)) 34 | } 35 | -------------------------------------------------------------------------------- /uploader/package.go: -------------------------------------------------------------------------------- 1 | package uploader 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | -------------------------------------------------------------------------------- /uploader/prefix_finder.go: -------------------------------------------------------------------------------- 1 | package uploader 2 | 3 | //counterfeiter:generate --fake-name FakeS3PrefixFetcher . S3PrefixFetcher 4 | type S3PrefixFetcher interface { 5 | S3PrefixForProductSlug(productSlug string) (string, error) 6 | } 7 | 8 | type PrefixFetcher struct { 9 | productSlug string 10 | s3PrefixFetcher S3PrefixFetcher 11 | } 12 | 13 | func NewPrefixFetcher(fetcher S3PrefixFetcher, productSlug string) PrefixFetcher { 14 | return PrefixFetcher{ 15 | productSlug: productSlug, 16 | s3PrefixFetcher: fetcher, 17 | } 18 | } 19 | 20 | func (pf *PrefixFetcher) GetPrefix() (string, error) { 21 | return pf.s3PrefixFetcher.S3PrefixForProductSlug(pf.productSlug) 22 | } 23 | -------------------------------------------------------------------------------- /uploader/prefix_finder_test.go: -------------------------------------------------------------------------------- 1 | package uploader_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | . "github.com/pivotal-cf/pivnet-resource/v3/uploader" 7 | "github.com/pivotal-cf/pivnet-resource/v3/uploader/uploaderfakes" 8 | ) 9 | 10 | var _ = Describe("PrefixFetcher", func() { 11 | Context("GetPrefix", func() { 12 | It("returns the product file prefix", func() { 13 | productSlug := "product-slug" 14 | productPrefix := "/my-product/file-prefix" 15 | fakeS3PrefixFetcher := &uploaderfakes.FakeS3PrefixFetcher{} 16 | fakeS3PrefixFetcher.S3PrefixForProductSlugReturns(productPrefix, nil) 17 | 18 | prefixFetcher := NewPrefixFetcher(fakeS3PrefixFetcher, productSlug) 19 | prefix, err := prefixFetcher.GetPrefix() 20 | 21 | Expect(err).NotTo(HaveOccurred()) 22 | Expect(prefix).To(Equal(productPrefix)) 23 | }) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /uploader/uploader.go: -------------------------------------------------------------------------------- 1 | package uploader 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "strings" 7 | ) 8 | 9 | //counterfeiter:generate --fake-name FakeTransport . transport 10 | type transport interface { 11 | Upload(fileGlob string, filepathPrefix string, sourcesDir string) error 12 | } 13 | 14 | type Client struct { 15 | filepathPrefix string 16 | sourcesDir string 17 | 18 | transport transport 19 | } 20 | 21 | type Config struct { 22 | FilepathPrefix string 23 | SourcesDir string 24 | 25 | Transport transport 26 | } 27 | 28 | func NewClient(config Config) *Client { 29 | return &Client{ 30 | filepathPrefix: config.FilepathPrefix, 31 | sourcesDir: config.SourcesDir, 32 | 33 | transport: config.Transport, 34 | } 35 | } 36 | 37 | func (c Client) UploadFile(exactGlob string) error { 38 | _, remoteDir, err := c.ComputeAWSObjectKey(exactGlob) 39 | if err != nil { 40 | return err 41 | } 42 | 43 | err = c.transport.Upload( 44 | exactGlob, 45 | remoteDir, 46 | c.sourcesDir, 47 | ) 48 | if err != nil { 49 | return err 50 | } 51 | 52 | return nil 53 | } 54 | 55 | func (c Client) ComputeAWSObjectKey(exactGlob string) (string, string, error) { 56 | if exactGlob == "" { 57 | return "", "", fmt.Errorf("glob must not be empty") 58 | } 59 | 60 | remoteDir := c.filepathPrefix 61 | 62 | filename := filepath.Base(exactGlob) 63 | if !strings.HasSuffix(remoteDir, "/") { 64 | remoteDir += "/" 65 | } 66 | 67 | if strings.HasPrefix(remoteDir, "/") { 68 | remoteDir = strings.TrimPrefix(remoteDir, "/") 69 | } 70 | 71 | remotePath := fmt.Sprintf("%s%s", remoteDir, filename) 72 | return remotePath, remoteDir, nil 73 | } 74 | -------------------------------------------------------------------------------- /uploader/uploader_suite_test.go: -------------------------------------------------------------------------------- 1 | package uploader_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestUploader(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Uploader Suite") 13 | } 14 | -------------------------------------------------------------------------------- /uploader/uploader_test.go: -------------------------------------------------------------------------------- 1 | package uploader_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/pivotal-cf/pivnet-resource/v3/uploader" 7 | "github.com/pivotal-cf/pivnet-resource/v3/uploader/uploaderfakes" 8 | "errors" 9 | "fmt" 10 | ) 11 | 12 | var _ = Describe("Uploader", func() { 13 | var ( 14 | fakeTransport *uploaderfakes.FakeTransport 15 | uploaderConfig uploader.Config 16 | uploaderClient *uploader.Client 17 | 18 | exactGlob string 19 | tempDir string 20 | 21 | filepathPrefix string 22 | ) 23 | 24 | BeforeEach(func() { 25 | fakeTransport = &uploaderfakes.FakeTransport{} 26 | 27 | filepathPrefix = "product-files/my-product-slug" 28 | exactGlob = "my-product-file" 29 | tempDir = "my/temp/dir" 30 | }) 31 | 32 | JustBeforeEach(func() { 33 | uploaderConfig = uploader.Config{ 34 | FilepathPrefix: filepathPrefix, 35 | Transport: fakeTransport, 36 | SourcesDir: tempDir, 37 | } 38 | 39 | uploaderClient = uploader.NewClient(uploaderConfig) 40 | }) 41 | 42 | Describe("UploadFile", func() { 43 | It("invokes the transport with correct args", func() { 44 | err := uploaderClient.UploadFile(exactGlob) 45 | Expect(err).NotTo(HaveOccurred()) 46 | 47 | Expect(fakeTransport.UploadCallCount()).To(Equal(1)) 48 | 49 | glob, remoteDir, sourcesDir := fakeTransport.UploadArgsForCall(0) 50 | Expect(glob).To(Equal(exactGlob)) 51 | Expect(remoteDir).To(Equal(filepathPrefix + "/")) 52 | Expect(sourcesDir).To(Equal(tempDir)) 53 | }) 54 | 55 | Context("when the transport exits with error", func() { 56 | BeforeEach(func() { 57 | fakeTransport.UploadReturns(errors.New("some error")) 58 | }) 59 | 60 | It("propagates errors", func() { 61 | err := uploaderClient.UploadFile("foo") 62 | Expect(err).To(HaveOccurred()) 63 | 64 | Expect(err.Error()).To(ContainSubstring("some error")) 65 | }) 66 | }) 67 | 68 | Context("when the glob is empty", func() { 69 | It("returns an error", func() { 70 | err := uploaderClient.UploadFile("") 71 | Expect(err).To(HaveOccurred()) 72 | Expect(err.Error()).To(ContainSubstring("glob")) 73 | }) 74 | }) 75 | }) 76 | 77 | Describe("ComputeAWSObjectKey", func() { 78 | It("computes the correct aws object key", func() { 79 | remotePath, remoteDir, err := uploaderClient.ComputeAWSObjectKey(exactGlob) 80 | 81 | Expect(err).NotTo(HaveOccurred()) 82 | Expect(remotePath).To(Equal(fmt.Sprint(filepathPrefix, "/", exactGlob))) 83 | Expect(remoteDir).To(Equal(fmt.Sprint(filepathPrefix, "/"))) 84 | }) 85 | 86 | Context("file path Prefix starts with a '/'", func() { 87 | It("removes the '/' form the prefix", func() { 88 | filepathPrefix = "/product-files/my-product-slug" 89 | expectedFilePathPrefix := "product-files/my-product-slug" 90 | remotePath, remoteDir, err := uploaderClient.ComputeAWSObjectKey(exactGlob) 91 | 92 | Expect(err).NotTo(HaveOccurred()) 93 | Expect(remotePath).To(Equal(fmt.Sprint(expectedFilePathPrefix, "/", exactGlob))) 94 | Expect(remoteDir).To(Equal(fmt.Sprint(expectedFilePathPrefix, "/"))) 95 | }) 96 | }) 97 | }) 98 | }) 99 | -------------------------------------------------------------------------------- /uploader/uploaderfakes/fake_s3prefix_fetcher.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package uploaderfakes 3 | 4 | import ( 5 | "sync" 6 | 7 | "github.com/pivotal-cf/pivnet-resource/v3/uploader" 8 | ) 9 | 10 | type FakeS3PrefixFetcher struct { 11 | S3PrefixForProductSlugStub func(string) (string, error) 12 | s3PrefixForProductSlugMutex sync.RWMutex 13 | s3PrefixForProductSlugArgsForCall []struct { 14 | arg1 string 15 | } 16 | s3PrefixForProductSlugReturns struct { 17 | result1 string 18 | result2 error 19 | } 20 | s3PrefixForProductSlugReturnsOnCall map[int]struct { 21 | result1 string 22 | result2 error 23 | } 24 | invocations map[string][][]interface{} 25 | invocationsMutex sync.RWMutex 26 | } 27 | 28 | func (fake *FakeS3PrefixFetcher) S3PrefixForProductSlug(arg1 string) (string, error) { 29 | fake.s3PrefixForProductSlugMutex.Lock() 30 | ret, specificReturn := fake.s3PrefixForProductSlugReturnsOnCall[len(fake.s3PrefixForProductSlugArgsForCall)] 31 | fake.s3PrefixForProductSlugArgsForCall = append(fake.s3PrefixForProductSlugArgsForCall, struct { 32 | arg1 string 33 | }{arg1}) 34 | stub := fake.S3PrefixForProductSlugStub 35 | fakeReturns := fake.s3PrefixForProductSlugReturns 36 | fake.recordInvocation("S3PrefixForProductSlug", []interface{}{arg1}) 37 | fake.s3PrefixForProductSlugMutex.Unlock() 38 | if stub != nil { 39 | return stub(arg1) 40 | } 41 | if specificReturn { 42 | return ret.result1, ret.result2 43 | } 44 | return fakeReturns.result1, fakeReturns.result2 45 | } 46 | 47 | func (fake *FakeS3PrefixFetcher) S3PrefixForProductSlugCallCount() int { 48 | fake.s3PrefixForProductSlugMutex.RLock() 49 | defer fake.s3PrefixForProductSlugMutex.RUnlock() 50 | return len(fake.s3PrefixForProductSlugArgsForCall) 51 | } 52 | 53 | func (fake *FakeS3PrefixFetcher) S3PrefixForProductSlugCalls(stub func(string) (string, error)) { 54 | fake.s3PrefixForProductSlugMutex.Lock() 55 | defer fake.s3PrefixForProductSlugMutex.Unlock() 56 | fake.S3PrefixForProductSlugStub = stub 57 | } 58 | 59 | func (fake *FakeS3PrefixFetcher) S3PrefixForProductSlugArgsForCall(i int) string { 60 | fake.s3PrefixForProductSlugMutex.RLock() 61 | defer fake.s3PrefixForProductSlugMutex.RUnlock() 62 | argsForCall := fake.s3PrefixForProductSlugArgsForCall[i] 63 | return argsForCall.arg1 64 | } 65 | 66 | func (fake *FakeS3PrefixFetcher) S3PrefixForProductSlugReturns(result1 string, result2 error) { 67 | fake.s3PrefixForProductSlugMutex.Lock() 68 | defer fake.s3PrefixForProductSlugMutex.Unlock() 69 | fake.S3PrefixForProductSlugStub = nil 70 | fake.s3PrefixForProductSlugReturns = struct { 71 | result1 string 72 | result2 error 73 | }{result1, result2} 74 | } 75 | 76 | func (fake *FakeS3PrefixFetcher) S3PrefixForProductSlugReturnsOnCall(i int, result1 string, result2 error) { 77 | fake.s3PrefixForProductSlugMutex.Lock() 78 | defer fake.s3PrefixForProductSlugMutex.Unlock() 79 | fake.S3PrefixForProductSlugStub = nil 80 | if fake.s3PrefixForProductSlugReturnsOnCall == nil { 81 | fake.s3PrefixForProductSlugReturnsOnCall = make(map[int]struct { 82 | result1 string 83 | result2 error 84 | }) 85 | } 86 | fake.s3PrefixForProductSlugReturnsOnCall[i] = struct { 87 | result1 string 88 | result2 error 89 | }{result1, result2} 90 | } 91 | 92 | func (fake *FakeS3PrefixFetcher) Invocations() map[string][][]interface{} { 93 | fake.invocationsMutex.RLock() 94 | defer fake.invocationsMutex.RUnlock() 95 | fake.s3PrefixForProductSlugMutex.RLock() 96 | defer fake.s3PrefixForProductSlugMutex.RUnlock() 97 | copiedInvocations := map[string][][]interface{}{} 98 | for key, value := range fake.invocations { 99 | copiedInvocations[key] = value 100 | } 101 | return copiedInvocations 102 | } 103 | 104 | func (fake *FakeS3PrefixFetcher) recordInvocation(key string, args []interface{}) { 105 | fake.invocationsMutex.Lock() 106 | defer fake.invocationsMutex.Unlock() 107 | if fake.invocations == nil { 108 | fake.invocations = map[string][][]interface{}{} 109 | } 110 | if fake.invocations[key] == nil { 111 | fake.invocations[key] = [][]interface{}{} 112 | } 113 | fake.invocations[key] = append(fake.invocations[key], args) 114 | } 115 | 116 | var _ uploader.S3PrefixFetcher = new(FakeS3PrefixFetcher) 117 | -------------------------------------------------------------------------------- /uploader/uploaderfakes/fake_transport.go: -------------------------------------------------------------------------------- 1 | // Code generated by counterfeiter. DO NOT EDIT. 2 | package uploaderfakes 3 | 4 | import ( 5 | "sync" 6 | ) 7 | 8 | type FakeTransport struct { 9 | UploadStub func(string, string, string) error 10 | uploadMutex sync.RWMutex 11 | uploadArgsForCall []struct { 12 | arg1 string 13 | arg2 string 14 | arg3 string 15 | } 16 | uploadReturns struct { 17 | result1 error 18 | } 19 | uploadReturnsOnCall map[int]struct { 20 | result1 error 21 | } 22 | invocations map[string][][]interface{} 23 | invocationsMutex sync.RWMutex 24 | } 25 | 26 | func (fake *FakeTransport) Upload(arg1 string, arg2 string, arg3 string) error { 27 | fake.uploadMutex.Lock() 28 | ret, specificReturn := fake.uploadReturnsOnCall[len(fake.uploadArgsForCall)] 29 | fake.uploadArgsForCall = append(fake.uploadArgsForCall, struct { 30 | arg1 string 31 | arg2 string 32 | arg3 string 33 | }{arg1, arg2, arg3}) 34 | stub := fake.UploadStub 35 | fakeReturns := fake.uploadReturns 36 | fake.recordInvocation("Upload", []interface{}{arg1, arg2, arg3}) 37 | fake.uploadMutex.Unlock() 38 | if stub != nil { 39 | return stub(arg1, arg2, arg3) 40 | } 41 | if specificReturn { 42 | return ret.result1 43 | } 44 | return fakeReturns.result1 45 | } 46 | 47 | func (fake *FakeTransport) UploadCallCount() int { 48 | fake.uploadMutex.RLock() 49 | defer fake.uploadMutex.RUnlock() 50 | return len(fake.uploadArgsForCall) 51 | } 52 | 53 | func (fake *FakeTransport) UploadCalls(stub func(string, string, string) error) { 54 | fake.uploadMutex.Lock() 55 | defer fake.uploadMutex.Unlock() 56 | fake.UploadStub = stub 57 | } 58 | 59 | func (fake *FakeTransport) UploadArgsForCall(i int) (string, string, string) { 60 | fake.uploadMutex.RLock() 61 | defer fake.uploadMutex.RUnlock() 62 | argsForCall := fake.uploadArgsForCall[i] 63 | return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 64 | } 65 | 66 | func (fake *FakeTransport) UploadReturns(result1 error) { 67 | fake.uploadMutex.Lock() 68 | defer fake.uploadMutex.Unlock() 69 | fake.UploadStub = nil 70 | fake.uploadReturns = struct { 71 | result1 error 72 | }{result1} 73 | } 74 | 75 | func (fake *FakeTransport) UploadReturnsOnCall(i int, result1 error) { 76 | fake.uploadMutex.Lock() 77 | defer fake.uploadMutex.Unlock() 78 | fake.UploadStub = nil 79 | if fake.uploadReturnsOnCall == nil { 80 | fake.uploadReturnsOnCall = make(map[int]struct { 81 | result1 error 82 | }) 83 | } 84 | fake.uploadReturnsOnCall[i] = struct { 85 | result1 error 86 | }{result1} 87 | } 88 | 89 | func (fake *FakeTransport) Invocations() map[string][][]interface{} { 90 | fake.invocationsMutex.RLock() 91 | defer fake.invocationsMutex.RUnlock() 92 | fake.uploadMutex.RLock() 93 | defer fake.uploadMutex.RUnlock() 94 | copiedInvocations := map[string][][]interface{}{} 95 | for key, value := range fake.invocations { 96 | copiedInvocations[key] = value 97 | } 98 | return copiedInvocations 99 | } 100 | 101 | func (fake *FakeTransport) recordInvocation(key string, args []interface{}) { 102 | fake.invocationsMutex.Lock() 103 | defer fake.invocationsMutex.Unlock() 104 | if fake.invocations == nil { 105 | fake.invocations = map[string][][]interface{}{} 106 | } 107 | if fake.invocations[key] == nil { 108 | fake.invocations[key] = [][]interface{}{} 109 | } 110 | fake.invocations[key] = append(fake.invocations[key], args) 111 | } 112 | -------------------------------------------------------------------------------- /useragent/useragent.go: -------------------------------------------------------------------------------- 1 | package useragent 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | func UserAgent(version, containerType, productSlug string) string { 11 | // check containers 12 | externalURL := os.Getenv("EXTERNAL_URL") 13 | resourceName := os.Getenv("RESOURCE_NAME") 14 | pipelineName := os.Getenv("PIPELINE_NAME") 15 | 16 | // check container 17 | if resourceName != "" { 18 | return strings.Trim( 19 | strconv.QuoteToASCII( 20 | fmt.Sprintf( 21 | "pivnet-resource/%s (%s/pipelines/%s/resources/%s -- %s/%s)", 22 | version, 23 | externalURL, 24 | pipelineName, 25 | resourceName, 26 | resourceName, 27 | containerType, 28 | ), 29 | ), "\"") 30 | } 31 | 32 | // in/out containers 33 | atcExternalURL := os.Getenv("ATC_EXTERNAL_URL") 34 | 35 | buildPipelineName := os.Getenv("BUILD_PIPELINE_NAME") 36 | buildJobName := os.Getenv("BUILD_JOB_NAME") 37 | buildName := os.Getenv("BUILD_NAME") 38 | 39 | return strings.Trim( 40 | strconv.QuoteToASCII( 41 | fmt.Sprintf( 42 | "pivnet-resource/%s (%s/pipelines/%s/jobs/%s/builds/%s -- %s/%s)", 43 | version, 44 | atcExternalURL, 45 | buildPipelineName, 46 | buildJobName, 47 | buildName, 48 | productSlug, 49 | containerType, 50 | ), 51 | ), "\"") 52 | } 53 | -------------------------------------------------------------------------------- /useragent/useragent_suite_test.go: -------------------------------------------------------------------------------- 1 | package useragent_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestUserAgent(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "UserAgent Suite") 13 | } 14 | -------------------------------------------------------------------------------- /validator/check_validator.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 7 | ) 8 | 9 | type CheckValidator struct { 10 | input concourse.CheckRequest 11 | } 12 | 13 | func NewCheckValidator(input concourse.CheckRequest) *CheckValidator { 14 | return &CheckValidator{ 15 | input: input, 16 | } 17 | } 18 | 19 | func (v CheckValidator) Validate() error { 20 | if v.input.Source.APIToken == "" { 21 | return fmt.Errorf("%s must be provided", "api_token") 22 | } 23 | 24 | if v.input.Source.ProductSlug == "" { 25 | return fmt.Errorf("%s must be provided", "product_slug") 26 | } 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /validator/check_validator_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 8 | "github.com/pivotal-cf/pivnet-resource/v3/validator" 9 | ) 10 | 11 | var _ = Describe("Check Validator", func() { 12 | var ( 13 | checkRequest concourse.CheckRequest 14 | v *validator.CheckValidator 15 | 16 | apiToken string 17 | productSlug string 18 | ) 19 | 20 | BeforeEach(func() { 21 | apiToken = "some-api-token" 22 | productSlug = "some-productSlug" 23 | }) 24 | 25 | JustBeforeEach(func() { 26 | checkRequest = concourse.CheckRequest{ 27 | Source: concourse.Source{ 28 | APIToken: apiToken, 29 | ProductSlug: productSlug, 30 | }, 31 | } 32 | v = validator.NewCheckValidator(checkRequest) 33 | }) 34 | 35 | It("returns without error", func() { 36 | err := v.Validate() 37 | Expect(err).NotTo(HaveOccurred()) 38 | }) 39 | 40 | Context("when neither legacy API token nor UAA refresh token are provided", func() { 41 | BeforeEach(func() { 42 | apiToken = "" 43 | }) 44 | 45 | It("returns an error", func() { 46 | err := v.Validate() 47 | Expect(err).To(HaveOccurred()) 48 | Expect(err.Error()).To(MatchRegexp("api_token must be provided")) 49 | }) 50 | }) 51 | 52 | Context("when a UAA refresh token or legacy API token is provided", func() { 53 | It("returns without error", func() { 54 | err := v.Validate() 55 | Expect(err).NotTo(HaveOccurred()) 56 | }) 57 | }) 58 | 59 | Context("when no product slug is provided", func() { 60 | BeforeEach(func() { 61 | productSlug = "" 62 | }) 63 | 64 | It("returns an error", func() { 65 | err := v.Validate() 66 | Expect(err).To(HaveOccurred()) 67 | Expect(err.Error()).To(MatchRegexp(".*product_slug.*provided")) 68 | }) 69 | }) 70 | }) 71 | -------------------------------------------------------------------------------- /validator/in_validator.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 7 | ) 8 | 9 | type InValidator struct { 10 | input concourse.InRequest 11 | } 12 | 13 | func NewInValidator(input concourse.InRequest) *InValidator { 14 | return &InValidator{ 15 | input: input, 16 | } 17 | } 18 | 19 | func (v InValidator) Validate() error { 20 | if v.input.Source.APIToken == "" { 21 | return fmt.Errorf("%s must be provided", "api_token") 22 | } 23 | 24 | if v.input.Source.ProductSlug == "" { 25 | return fmt.Errorf("%s must be provided", "product_slug") 26 | } 27 | 28 | if v.input.Version.ProductVersion == "" { 29 | return fmt.Errorf("%s must be provided", "product_version") 30 | } 31 | 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /validator/in_validator_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 8 | "github.com/pivotal-cf/pivnet-resource/v3/validator" 9 | ) 10 | 11 | var _ = Describe("In Validator", func() { 12 | var ( 13 | inRequest concourse.InRequest 14 | v *validator.InValidator 15 | apiToken string 16 | productSlug string 17 | version string 18 | ) 19 | 20 | BeforeEach(func() { 21 | apiToken = "some-api-token" 22 | productSlug = "some-productSlug" 23 | version = "some-product-version" 24 | }) 25 | 26 | JustBeforeEach(func() { 27 | inRequest = concourse.InRequest{ 28 | Source: concourse.Source{ 29 | APIToken: apiToken, 30 | ProductSlug: productSlug, 31 | }, 32 | Params: concourse.InParams{}, 33 | Version: concourse.Version{ 34 | ProductVersion: version, 35 | }, 36 | } 37 | 38 | v = validator.NewInValidator(inRequest) 39 | }) 40 | 41 | It("returns without error", func() { 42 | err := v.Validate() 43 | Expect(err).NotTo(HaveOccurred()) 44 | }) 45 | 46 | 47 | Context("when neither UAA refresh token nor legacy API token are provided", func() { 48 | BeforeEach(func() { 49 | apiToken = "" 50 | }) 51 | 52 | It("returns an error", func() { 53 | err := v.Validate() 54 | Expect(err).To(HaveOccurred()) 55 | Expect(err.Error()).To(MatchRegexp("api_token must be provided")) 56 | }) 57 | }) 58 | 59 | Context("when UAA refresh token or legacy API token is provided", func() { 60 | It("returns without error", func() { 61 | err := v.Validate() 62 | Expect(err).NotTo(HaveOccurred()) 63 | }) 64 | }) 65 | 66 | Context("when no product slug is provided", func() { 67 | BeforeEach(func() { 68 | productSlug = "" 69 | }) 70 | 71 | It("returns an error", func() { 72 | err := v.Validate() 73 | Expect(err).To(HaveOccurred()) 74 | Expect(err.Error()).To(MatchRegexp(".*product_slug.*provided")) 75 | }) 76 | }) 77 | 78 | Context("when no product version is provided", func() { 79 | BeforeEach(func() { 80 | version = "" 81 | }) 82 | 83 | It("returns an error", func() { 84 | err := v.Validate() 85 | Expect(err).NotTo(BeNil()) 86 | Expect(err.Error()).To(MatchRegexp(".*product_version.*provided")) 87 | }) 88 | }) 89 | }) 90 | -------------------------------------------------------------------------------- /validator/out_validator.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 7 | ) 8 | 9 | type OutValidator struct { 10 | input concourse.OutRequest 11 | } 12 | 13 | func NewOutValidator(input concourse.OutRequest) *OutValidator { 14 | return &OutValidator{ 15 | input: input, 16 | } 17 | } 18 | 19 | func (v OutValidator) Validate() error { 20 | if v.input.Source.APIToken == "" { 21 | return fmt.Errorf("%s must be provided", "api_token") 22 | } 23 | 24 | if v.input.Source.ProductSlug == "" { 25 | return fmt.Errorf("%s must be provided", "product_slug") 26 | } 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /validator/out_validator_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/pivotal-cf/pivnet-resource/v3/concourse" 7 | "github.com/pivotal-cf/pivnet-resource/v3/validator" 8 | ) 9 | 10 | var _ = Describe("Out Validator", func() { 11 | var ( 12 | 13 | apiToken string 14 | productSlug string 15 | fileGlob string 16 | 17 | outRequest concourse.OutRequest 18 | v *validator.OutValidator 19 | ) 20 | 21 | BeforeEach(func() { 22 | apiToken = "some-api-token" 23 | productSlug = "some-product" 24 | 25 | fileGlob = "" 26 | }) 27 | 28 | JustBeforeEach(func() { 29 | outRequest = concourse.OutRequest{ 30 | Source: concourse.Source{ 31 | APIToken: apiToken, 32 | ProductSlug: productSlug, 33 | }, 34 | Params: concourse.OutParams{ 35 | FileGlob: fileGlob, 36 | }, 37 | } 38 | 39 | v = validator.NewOutValidator(outRequest) 40 | }) 41 | 42 | It("returns without error", func() { 43 | Expect(v.Validate()).NotTo(HaveOccurred()) 44 | }) 45 | 46 | Context("when neither UAA refresh token nor legacy API token are provided", func() { 47 | BeforeEach(func() { 48 | apiToken = "" 49 | }) 50 | 51 | It("returns an error", func() { 52 | err := v.Validate() 53 | Expect(err).To(HaveOccurred()) 54 | Expect(err.Error()).To(MatchRegexp("api_token must be provided")) 55 | }) 56 | }) 57 | 58 | Context("when UAA reresh token or legacy API token is provided", func() { 59 | It("returns without error", func() { 60 | err := v.Validate() 61 | Expect(err).NotTo(HaveOccurred()) 62 | }) 63 | }) 64 | 65 | Context("when no product slug is provided", func() { 66 | BeforeEach(func() { 67 | productSlug = "" 68 | }) 69 | 70 | It("returns an error", func() { 71 | err := v.Validate() 72 | Expect(err).To(HaveOccurred()) 73 | 74 | Expect(err.Error()).To(MatchRegexp(".*product_slug.*provided")) 75 | }) 76 | }) 77 | 78 | Context("when file glob is not provided", func() { 79 | BeforeEach(func() { 80 | fileGlob = "" 81 | }) 82 | 83 | It("returns without error", func() { 84 | err := v.Validate() 85 | Expect(err).NotTo(HaveOccurred()) 86 | }) 87 | }) 88 | 89 | }) 90 | -------------------------------------------------------------------------------- /validator/validator_suite_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestValidator(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Validator Suite") 13 | } 14 | -------------------------------------------------------------------------------- /versions/versions.go: -------------------------------------------------------------------------------- 1 | package versions 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | const ( 9 | fingerprintDelimiter = "#" 10 | ) 11 | 12 | func Since(versions []string, since string) ([]string, error) { 13 | for i, v := range versions { 14 | if v == since { 15 | return versions[:i+1], nil 16 | } 17 | } 18 | 19 | return versions[:1], nil 20 | } 21 | 22 | func Reverse(versions []string) ([]string, error) { 23 | var reversed []string 24 | for i := len(versions) - 1; i >= 0; i-- { 25 | reversed = append(reversed, versions[i]) 26 | } 27 | 28 | return reversed, nil 29 | } 30 | 31 | func SplitIntoVersionAndFingerprint(versionWithFingerprint string) (string, string, error) { 32 | split := strings.Split(versionWithFingerprint, fingerprintDelimiter) 33 | if len(split) != 2 { 34 | return "", "", fmt.Errorf("Invalid version and Fingerprint: %s", versionWithFingerprint) 35 | } 36 | return split[0], split[1], nil 37 | } 38 | 39 | func CombineVersionAndFingerprint(version string, fingerprint string) (string, error) { 40 | if fingerprint == "" { 41 | return version, nil 42 | } 43 | return combineVersionAndFingerprint(version, fingerprint), nil 44 | } 45 | 46 | func combineVersionAndFingerprint(version string, fingerprint string) string { 47 | return fmt.Sprintf("%s%s%s", version, fingerprintDelimiter, fingerprint) 48 | } 49 | -------------------------------------------------------------------------------- /versions/versions_suite_test.go: -------------------------------------------------------------------------------- 1 | package versions_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestVersions(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Versions Suite") 13 | } 14 | -------------------------------------------------------------------------------- /versions/versions_test.go: -------------------------------------------------------------------------------- 1 | package versions_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/pivotal-cf/pivnet-resource/v3/versions" 7 | ) 8 | 9 | var _ = Describe("Versions", func() { 10 | Describe("Since", func() { 11 | var ( 12 | allVersions []string 13 | version string 14 | ) 15 | 16 | BeforeEach(func() { 17 | allVersions = []string{} 18 | version = "" 19 | }) 20 | 21 | Context("when the provided version is the newest", func() { 22 | var ( 23 | allVersions []string 24 | version string 25 | ) 26 | 27 | BeforeEach(func() { 28 | allVersions = []string{"1.2.3#abc", "1.3.2#def"} 29 | version = "1.2.3#abc" 30 | }) 31 | 32 | It("returns the latest version", func() { 33 | versions, _ := versions.Since(allVersions, version) 34 | 35 | Expect(versions).To(HaveLen(1)) 36 | Expect(versions).To(Equal([]string{"1.2.3#abc"})) 37 | }) 38 | }) 39 | 40 | Context("when provided version is present but not the newest", func() { 41 | BeforeEach(func() { 42 | allVersions = []string{"newest version", "middle version", "older version", "last version"} 43 | version = "older version" 44 | }) 45 | 46 | It("returns new versions", func() { 47 | versions, _ := versions.Since(allVersions, version) 48 | 49 | Expect(versions).To(Equal([]string{"newest version", "middle version", "older version"})) 50 | }) 51 | }) 52 | 53 | Context("When the version is not present", func() { 54 | BeforeEach(func() { 55 | allVersions = []string{"1.2.3#abc", "1.3.2#def"} 56 | version = "1.3.2" 57 | }) 58 | 59 | It("returns the newest version", func() { 60 | versions, _ := versions.Since(allVersions, version) 61 | 62 | Expect(versions).To(Equal([]string{"1.2.3#abc"})) 63 | }) 64 | }) 65 | }) 66 | 67 | Describe("Reverse", func() { 68 | It("returns reversed ordered versions because concourse expects them that way", func() { 69 | versions, err := versions.Reverse([]string{"v201", "v178", "v120", "v200"}) 70 | 71 | Expect(err).NotTo(HaveOccurred()) 72 | Expect(versions).To(Equal([]string{"v200", "v120", "v178", "v201"})) 73 | }) 74 | }) 75 | 76 | Describe("SplitIntoVersionAndFingerprint", func() { 77 | var ( 78 | input string 79 | ) 80 | 81 | BeforeEach(func() { 82 | input = "some.version#my-fingerprint" 83 | }) 84 | 85 | It("splits without error", func() { 86 | version, fingerprint, err := versions.SplitIntoVersionAndFingerprint(input) 87 | 88 | Expect(err).NotTo(HaveOccurred()) 89 | Expect(version).To(Equal("some.version")) 90 | Expect(fingerprint).To(Equal("my-fingerprint")) 91 | }) 92 | 93 | Context("when the input does not contain enough delimiters", func() { 94 | BeforeEach(func() { 95 | input = "some.version" 96 | }) 97 | 98 | It("returns error", func() { 99 | _, _, err := versions.SplitIntoVersionAndFingerprint(input) 100 | Expect(err).To(HaveOccurred()) 101 | }) 102 | }) 103 | 104 | Context("when the input contains too many delimiters", func() { 105 | BeforeEach(func() { 106 | input = "some.version#fingerprint-1#-fingerprint-2" 107 | }) 108 | 109 | It("returns error", func() { 110 | _, _, err := versions.SplitIntoVersionAndFingerprint(input) 111 | Expect(err).To(HaveOccurred()) 112 | }) 113 | }) 114 | }) 115 | 116 | Describe("CombineVersionAndFingerprint", func() { 117 | var ( 118 | version string 119 | fingerprint string 120 | ) 121 | 122 | BeforeEach(func() { 123 | version = "some.version" 124 | fingerprint = "my-fingerprint" 125 | }) 126 | 127 | It("combines without error", func() { 128 | versionWithFingerprint, err := versions.CombineVersionAndFingerprint(version, fingerprint) 129 | 130 | Expect(err).NotTo(HaveOccurred()) 131 | Expect(versionWithFingerprint).To(Equal("some.version#my-fingerprint")) 132 | }) 133 | 134 | Context("when the fingerprint is empty", func() { 135 | BeforeEach(func() { 136 | fingerprint = "" 137 | }) 138 | 139 | It("does not include the #", func() { 140 | versionWithFingerprint, err := versions.CombineVersionAndFingerprint(version, fingerprint) 141 | 142 | Expect(err).NotTo(HaveOccurred()) 143 | Expect(versionWithFingerprint).To(Equal("some.version")) 144 | }) 145 | }) 146 | }) 147 | }) 148 | --------------------------------------------------------------------------------