From 43a939a115e48a066395a25861470f584cf8e91d Mon Sep 17 00:00:00 2001 From: AL Berez Date: Tue, 29 Oct 2024 09:31:37 -0700 Subject: [PATCH 01/21] Switch test environments to cfd bosh lites [v8] (#3270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Switch environment to cfd-bosh-lite * Turn off set_kernel_parameters to use cfd-bosh-lite * Expose shepherd configuration via repo variables * Update secrets path to bosh-lite * Expose TEST_FLAKE_ATTEMPTS and TEST_NODES * Set default FLAKE_ATTEMPTS * Bump gha test suit timeout from 60 to 120m * Enter nodes as workflow_dispatch input * Skip steps if SHEPHERD_LEASE_ID defined * Skip scaling tests that are testing CAPI * bosh-light environment default memory is 256Mb * Fixed the issue with force update of bosh * Delete created orgs during tests * Ensure that the orgName is empty for each test * Prevent double deletion of org * Lower number of tests running using client credentials to avoid flakes * Allow user to define namespace of the leased environment * Pass namespace of the lease to the reusable workflow Co-authored-by: João Pereira --- .github/ops-files/diego-cell-instances.yml | 4 + .../workflows/tests-integration-reusable.yml | 56 +++++---- .github/workflows/tests-integration.yml | 114 +++++++++++++++--- .gitignore | 2 + Makefile | 2 + integration/helpers/org_and_space.go | 12 +- .../shared/isolated/spaces_command_test.go | 4 + integration/shared/plugin/api_test.go | 53 +++++--- .../running_security_groups_command_test.go | 1 + .../v7/global/set_space_role_command_test.go | 1 + .../staging_security_groups_command_test.go | 1 + .../create_space_quota_command_test.go | 4 + .../v7/isolated/move_route_command_test.go | 2 + .../v7/isolated/org_users_command_test.go | 4 + .../v7/isolated/rename_org_command_test.go | 4 + integration/v7/isolated/scale_command_test.go | 28 +++-- .../isolated/security_groups_command_test.go | 1 + .../v7/isolated/services_command_test.go | 8 +- .../v7/isolated/share_private_domain_test.go | 5 + .../v7/isolated/share_route_command_test.go | 1 + .../v7/isolated/space_quota_command_test.go | 4 + .../v7/isolated/space_users_command_test.go | 4 + .../v7/isolated/spaces_command_test.go | 4 + integration/v7/isolated/start_command_test.go | 2 +- .../isolated/unshare_private_domain_test.go | 8 ++ .../v7/isolated/unshare_route_command_test.go | 1 + 26 files changed, 254 insertions(+), 76 deletions(-) diff --git a/.github/ops-files/diego-cell-instances.yml b/.github/ops-files/diego-cell-instances.yml index 19ea43d8077..6fff5cd2232 100644 --- a/.github/ops-files/diego-cell-instances.yml +++ b/.github/ops-files/diego-cell-instances.yml @@ -2,3 +2,7 @@ - type: replace path: /instance_groups/name=diego-cell/instances value: 4 + +- type: replace + path: /instance_groups/name=isolated-diego-cell/jobs/name=rep/properties?/set_kernel_parameters + value: false diff --git a/.github/workflows/tests-integration-reusable.yml b/.github/workflows/tests-integration-reusable.yml index 36bdc768c9f..4e1ee3cc356 100644 --- a/.github/workflows/tests-integration-reusable.yml +++ b/.github/workflows/tests-integration-reusable.yml @@ -3,7 +3,7 @@ # secrets.CLIENT_SECRET # secrets.GITHUB_TOKEN # secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN -# vars.SHEPHERD_POOL_NAME +# vars.TEST_FLAKE_ATTEMPTS name: "pvt: run integration tests" @@ -22,17 +22,29 @@ on: lease-id: required: true type: string + lease-namespace: + required: false + type: string + default: 'tas-devex' gitRef: type: string default: ${{github.event.workflow_run.head_sha}} - + nodes: + type: string + default: "16" + +env: + NODES: ${{ inputs.nodes }} + FLAKE_ATTEMPTS: ${{ vars.TEST_FLAKE_ATTEMPTS || '4' }} + jobs: run-integration-tests: defaults: run: shell: bash - runs-on: ${{ inputs.os }} + runs-on: ${{ inputs.os }} container: us-west2-docker.pkg.dev/shepherd-268822/shepherd2/concourse-resource:latest + timeout-minutes: 120 steps: - name: Checkout cli uses: actions/checkout@v4 @@ -61,7 +73,9 @@ jobs: - name: Install Tools env: - account_token: ${{ secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN }} + account_token: ${{ secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN }} + lease_namespace: ${{ inputs.lease-namespace }} + lease_id: ${{ inputs.lease-id }} run: | go version @@ -95,22 +109,22 @@ jobs: apt-get install -y build-essential unzip shepherd login service-account ${account_token} - shepherd get lease ${{ inputs.lease-id }} --namespace tas-devex --json | jq .output > metadata.json + shepherd get lease ${lease_id} --namespace ${lease_namespace} --json | jq .output > metadata.json - name: Add CATS config if: ${{ inputs.name == 'cats' }} run: | set -eu - ENV=$(jq -r .name metadata.json) + env_name=$(jq -r .name metadata.json) API="$(jq -r .cf.api_url metadata.json)" DOMAIN=$(echo $API | sed "s/^api\.//") CF_INT_USERNAME="admin" - jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${ENV}.priv + jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${env_name}.priv eval "$(bbl print-env --metadata-file ./metadata.json)" credhub login - CF_INT_PASSWORD=$(credhub get -n /bosh-$ENV/cf/cf_admin_password | bosh interpolate --path /value -) + CF_INT_PASSWORD=$(credhub get -n /bosh-lite/cf/cf_admin_password | bosh interpolate --path /value -) cat << EOF | jq -S . > cats_config.json { @@ -184,26 +198,24 @@ jobs: --keep-going \ --randomize-all \ --skip-package=helpers \ - --nodes="12" \ - --flake-attempts=2 \ + --nodes="${NODES}" \ + --flake-attempts=${FLAKE_ATTEMPTS} \ --timeout="2h" \ --no-color - name: Run Integration Tests if: ${{ !inputs.run-with-client-creds && inputs.name != 'cats' }} run: | - ENV=$(cat metadata.json | jq -r '.name') - jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${ENV}.priv + env_name=$(cat metadata.json | jq -r '.name') + jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${env_name}.priv eval "$(bbl print-env --metadata-file ./metadata.json)" - export CF_INT_PASSWORD="$(credhub get -n /bosh-$ENV/cf/cf_admin_password | bosh interpolate --path /value -)" + export CF_INT_PASSWORD="$(credhub get -n /bosh-lite/cf/cf_admin_password | bosh interpolate --path /value -)" export CF_INT_OIDC_USERNAME="admin-oidc" - export CF_INT_OIDC_PASSWORD=$(credhub get -n /bosh-$ENV/cf/uaa_oidc_admin_password | bosh interpolate --path /value -) + export CF_INT_OIDC_PASSWORD=$(credhub get -n /bosh-lite/cf/uaa_oidc_admin_password | bosh interpolate --path /value -) API_URL="$(jq -r .cf.api_url metadata.json)" export CF_INT_API="https://$API_URL" export CF_DIAL_TIMEOUT=15 export CF_USERNAME=admin - export FLAKE_ATTEMPTS=2 - export NODES=16 export GOPATH=$PWD/go export PATH="$GOPATH/bin:$PATH" export PATH="$PWD/out:$PATH" @@ -223,18 +235,16 @@ jobs: CF_INT_CLIENT_ID: 'potato-face' CF_INT_CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} run: | - ENV=$(cat metadata.json | jq -r '.name') - jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${ENV}.priv + env_name=$(cat metadata.json | jq -r '.name') + jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${env_name}.priv eval "$(bbl print-env --metadata-file ./metadata.json)" - export CF_INT_PASSWORD="$(credhub get -n /bosh-$ENV/cf/cf_admin_password | bosh interpolate --path /value -)" + export CF_INT_PASSWORD="$(credhub get -n /bosh-lite/cf/cf_admin_password | bosh interpolate --path /value -)" export CF_INT_OIDC_USERNAME="admin-oidc" - export CF_INT_OIDC_PASSWORD=$(credhub get -n /bosh-$ENV/cf/uaa_oidc_admin_password | bosh interpolate --path /value -) + export CF_INT_OIDC_PASSWORD=$(credhub get -n /bosh-lite/cf/uaa_oidc_admin_password | bosh interpolate --path /value -) API_URL="$(jq -r .cf.api_url metadata.json)" export CF_INT_API="https://$API_URL" export CF_DIAL_TIMEOUT=15 export CF_USERNAME=admin - export FLAKE_ATTEMPTS=2 - export NODES=16 export GOPATH=$PWD/go export PATH="$GOPATH/bin:$PATH" export PATH="$PWD/out:$PATH" @@ -246,4 +256,4 @@ jobs: cf api ${CF_INT_API} --skip-ssl-validation cf auth - make integration-tests-full-ci \ No newline at end of file + make integration-tests-ci-client-creds diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index dc2624d9115..0961b74dccd 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -1,3 +1,14 @@ +# GitHub repo level Secrets and Variables + +# secrets.CLIENT_SECRET +# secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN +# vars.CAPI_RELEASE_VERSION +# vars.SHEPHERD_LEASE_DURATION +# vars.SHEPHERD_LEASE_NAMESPACE +# vars.SHEPHERD_TEMPLATE_ARGUMENT +# vars.SHEPHERD_TEMPLATE_NAME +# vars.SHEPHERD_TEMPLATE_NAMESPACE + name: "Tests: Integration" run-name: "Integration [${{ github.event_name }}: ${{ github.event.pull_request.head.sha || github.event.push.after || github.event.workflow_run.head_sha}}]: ${{ github.event.workflow_run.head_commit.message }}" @@ -14,6 +25,30 @@ on: - run-integration-tests-cf-env - run-integration-tests-cf-env-with-client-creds - run-cats-cf-env + nodes: + description: Number of test nodes + required: false + type: string + default: "12" + lease_id: + description: Pre-provisioned environment lease-id to use in tests + required: false + type: string + lease_namespace: + description: Pre-provisioned environment lease namespace to use in tests + required: false + type: string + run_unit_tests: + description: Run unit tests + required: false + type: boolean + default: true + reinstall_cfd: + description: Force re-installation of CFD + required: false + type: boolean + default: true + push: tags: - "v8.*" @@ -27,6 +62,10 @@ on: - "doc/**" - ".gitpod.yml" - "README.md" + +env: + SHEPHERD_LEASE_ID: ${{ inputs.lease_id }} + jobs: get-sha: runs-on: ubuntu-latest @@ -53,14 +92,17 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + if: ${{ inputs.run_unit_tests == 'true' }} with: ref: ${{needs.get-sha.outputs.gitRef}} - name: Set Up Go uses: actions/setup-go@v5 + if: ${{ inputs.run_unit_tests == 'true' }} with: go-version-file: go.mod check-latest: true - name: Run Units + if: ${{ inputs.run_unit_tests == 'true' }} run: make units claim-env: @@ -84,23 +126,57 @@ jobs: - name: claim id: claim env: - account_token: ${{ secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN }} - pool_name: ${{ vars.SHEPHERD_POOL_NAME }} - pool_namespace: official + account_token: ${{ secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN }} + template_argument: ${{ vars.SHEPHERD_TEMPLATE_ARGUMENT }} + template_name: ${{ vars.SHEPHERD_TEMPLATE_NAME || 'cfd-bosh-lite@1.0' }} + template_namespace: ${{ vars.SHEPHERD_TEMPLATE_NAMESPACE || 'official' }} + lease_duration: ${{ vars.SHEPHERD_LEASE_DURATION || '8h' }} + lease_namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} run: | shepherd login service-account ${account_token} - echo "shepherd create lease --duration 8h --pool ${pool_name} --pool-namespace ${pool_namespace} --namespace tas-devex --description 'CLI GHA'" - lease_id=$(shepherd create lease --duration 8h --pool ${pool_name} --pool-namespace ${pool_namespace} --namespace tas-devex --json | jq -r .id) - + if [[ -z $SHEPHERD_LEASE_ID ]]; then + + if [ -z "$template_argument" ]; then + export template_argument='{"gcp_region": "us-west2", + "vm_type": "n1-standard-8", + "root_disk_gb": 32, + "disk_pool_gb": 150, + "cfd_version": "", + "additional_opsfiles_b64": ""}' + fi + + lease_id=$( shepherd create lease \ + --template-argument "$template_argument" \ + --template-namespace "${template_namespace}" \ + --template "${template_name}" \ + --namespace "${lease_namespace}" \ + --duration "${lease_duration}" \ + --description "Claimed by CF CLI workflow ${{ github.workflow_run.url }}" \ + --json \ + | jq -r .id + ) + else + lease_id=$SHEPHERD_LEASE_ID + fi + + echo "Shepherd lease ID: ${lease_id}" + # Give sometime for the lease to complete. Shepherd may take upto an 3 hours to create an env # if the pool is empty. count=0 while [ $count -lt 360 ] ; do sleep 30 - status=$(shepherd get lease ${lease_id} --namespace tas-devex --json | jq -r .status) + status=$( shepherd get lease ${lease_id} \ + --namespace ${lease_namespace} \ + --json \ + | jq -r .status + ) if [ $status == "LEASED" ] ; then - shepherd get lease ${lease_id} --namespace tas-devex --json | jq .output > metadata.json + shepherd get lease ${lease_id} \ + --namespace ${lease_namespace} \ + --json \ + | jq .output > metadata.json break elif [ $status == "FAILED" -o $status == "EXPIRED" ] ; then echo "There was an error obtaining the lease. Lease status is ${status}." @@ -115,7 +191,7 @@ jobs: echo "env name is ${env_name}" echo "leaseid=${lease_id}" >> "${GITHUB_OUTPUT}" - cf_deployment_version=$(jq -r '."cf-deployment_version"' metadata.json) + cf_deployment_version=$(jq -r '."cf_deployment_version"' metadata.json) echo "cf_deployment_version is ${cf_deployment_version}" echo "cf_deployment_version=${cf_deployment_version}" >> "${GITHUB_OUTPUT}" @@ -126,6 +202,7 @@ jobs: check-latest: true - name: Install Tools + if: ${{ (inputs.lease_id == '') || (inputs.reinstall_cfd == true) }} run: | go version @@ -145,11 +222,11 @@ jobs: apt-get install -y build-essential unzip - name: Upload latest CAPI release + if: ${{ (inputs.lease_id == '') || (inputs.reinstall_cfd == true) }} env: capi_release_version: ${{ vars.CAPI_RELEASE_VERSION }} run: | - if [ -z "$capi_release_version" ] - then + if [ -z "$capi_release_version" ]; then capi_release_version=$(curl -s https://api.github.com/repos/cloudfoundry/capi-release/releases/latest | jq -r .tag_name) fi @@ -162,6 +239,7 @@ jobs: bosh upload-release "https://bosh.io/d/github.com/cloudfoundry/capi-release?v=$capi_release_version" - name: Checkout cf-deployment + if: ${{ (inputs.lease_id == '') || (inputs.reinstall_cfd == true) }} uses: actions/checkout@v4 with: repository: cloudfoundry/cf-deployment @@ -169,12 +247,12 @@ jobs: ref: ${{steps.claim.outputs.cf_deployment_version}} - name: Deploy Isolation Segment and OIDC Provider + if: ${{ (inputs.lease_id == '') || (inputs.reinstall_cfd == true) }} run: | env_name=$(jq -r .name metadata.json) jq -r .bosh.jumpbox_private_key metadata.json > /tmp/${env_name}.priv eval "$(bbl print-env --metadata-file metadata.json)" - # deploy bosh -d cf manifest > /tmp/manifest.yml bosh interpolate /tmp/manifest.yml \ -o cf-deployment/operations/use-internal-lookup-for-route-services.yml \ @@ -204,6 +282,8 @@ jobs: name: Integration gitRef: ${{needs.get-sha.outputs.gitRef}} lease-id: ${{ needs.claim-env.outputs.leaseid }} + lease-namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} + nodes: ${{ inputs.nodes }} secrets: inherit run-integration-tests-cf-env-with-client-creds: @@ -220,6 +300,7 @@ jobs: name: Integration client creds gitRef: ${{needs.get-sha.outputs.gitRef}} lease-id: ${{ needs.claim-env.outputs.leaseid }} + lease-namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} secrets: inherit run-cats-cf-env: @@ -237,21 +318,24 @@ jobs: name: cats gitRef: ${{needs.get-sha.outputs.gitRef}} lease-id: ${{ needs.claim-env.outputs.leaseid }} + lease-namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} secrets: inherit unclaim-env: name: Unclaim environment + if: ${{ inputs.lease_id == '' }} runs-on: ubuntu-latest container: us-west2-docker.pkg.dev/shepherd-268822/shepherd2/concourse-resource:latest needs: - claim-env - run-cats-cf-env - if: always() steps: - name: unclaim env: - account_token: ${{ secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN }} + account_token: ${{ secrets.SHEPHERD_SERVICE_ACCOUNT_TOKEN }} + lease_namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} run: | shepherd login service-account ${account_token} set -x - shepherd delete lease ${{ needs.claim-env.outputs.leaseid }} --namespace tas-devex + shepherd delete lease ${{ needs.claim-env.outputs.leaseid }} \ + --namespace ${lease_namespace} diff --git a/.gitignore b/.gitignore index bdd84341efc..cc14c3edb44 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,5 @@ integration/assets/test_plugin/test_plugin ### VisualStudioCode ### .vscode +.secrets +.vars diff --git a/Makefile b/Makefile index 6ed3ce755a0..409563d4dec 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ CF_DIAL_TIMEOUT ?= 15 NODES ?= 10 +FLAKE_ATTEMPTS ?=5 PACKAGES ?= api actor command types util version integration/helpers LC_ALL = "en_US.UTF-8" @@ -130,6 +131,7 @@ integration-selfcontained: build install-test-deps integration-tests: build integration-cleanup integration-isolated integration-push integration-global integration-selfcontained ## Run all isolated, push, selfcontained, and global integration tests +integration-tests-ci-client-creds: build integration-cleanup integration-push integration-global integration-selfcontained i: integration-tests-full integration-full-tests: integration-tests-full diff --git a/integration/helpers/org_and_space.go b/integration/helpers/org_and_space.go index e098a3bcd16..c08150762eb 100644 --- a/integration/helpers/org_and_space.go +++ b/integration/helpers/org_and_space.go @@ -112,7 +112,7 @@ func GetSpaceGUID(spaceName string) string { } // QuickDeleteOrg deletes the org with the given name, if provided, using -// 'cf curl /v2/organizations... -X DELETE'. +// 'cf curl /v3/organizations... -X DELETE'. func QuickDeleteOrg(orgName string) { // If orgName is empty, the BeforeSuite has failed and attempting to delete // will produce a meaningless error. @@ -122,13 +122,13 @@ func QuickDeleteOrg(orgName string) { } guid := GetOrgGUID(orgName) - url := fmt.Sprintf("/v2/organizations/%s?recursive=true&async=true", guid) + url := fmt.Sprintf("/v3/organizations/%s", guid) session := CF("curl", "-X", "DELETE", url) Eventually(session).Should(Exit(0)) } // QuickDeleteOrgIfExists deletes the org with the given name, if it exists, using -// 'cf curl /v2/organizations... -X DELETE'. +// 'cf curl /v3/organizations... -X DELETE'. func QuickDeleteOrgIfExists(orgName string) { session := CF("org", "--guid", orgName) Eventually(session).Should(Exit()) @@ -136,16 +136,16 @@ func QuickDeleteOrgIfExists(orgName string) { return } guid := strings.TrimSpace(string(session.Out.Contents())) - url := fmt.Sprintf("/v2/organizations/%s?recursive=true&async=true", guid) + url := fmt.Sprintf("/v3/organizations/%s", guid) session = CF("curl", "-X", "DELETE", url) Eventually(session).Should(Exit()) } // QuickDeleteSpace deletes the space with the given name, if it exists, using -// 'cf curl /v2/spaces... -X DELETE'. +// 'cf curl /v3/spaces... -X DELETE'. func QuickDeleteSpace(spaceName string) { guid := GetSpaceGUID(spaceName) - url := fmt.Sprintf("/v2/spaces/%s?recursive=true&async=true", guid) + url := fmt.Sprintf("/v3/spaces/%s", guid) session := CF("curl", "-X", "DELETE", url) Eventually(session).Should(Exit(0)) } diff --git a/integration/shared/isolated/spaces_command_test.go b/integration/shared/isolated/spaces_command_test.go index 2fca098d47a..96ccccdc4d9 100644 --- a/integration/shared/isolated/spaces_command_test.go +++ b/integration/shared/isolated/spaces_command_test.go @@ -30,6 +30,10 @@ var _ = Describe("spaces command", func() { helpers.TargetOrg(orgName) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + When("there are no spaces", func() { It("displays no spaces found", func() { session := helpers.CF("spaces") diff --git a/integration/shared/plugin/api_test.go b/integration/shared/plugin/api_test.go index 8b2b4a56dde..8ffb206371f 100644 --- a/integration/shared/plugin/api_test.go +++ b/integration/shared/plugin/api_test.go @@ -13,11 +13,16 @@ import ( ) var _ = Describe("plugin API", func() { + var orgName string BeforeEach(func() { + orgName = "" installTestPlugin() }) AfterEach(func() { + if orgName != "" { + helpers.QuickDeleteOrg(orgName) + } uninstallTestPlugin() }) @@ -63,7 +68,7 @@ var _ = Describe("plugin API", func() { Describe("GetApp", func() { var appName string BeforeEach(func() { - createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() appName = helpers.PrefixedRandomName("APP") helpers.WithHelloWorldApp(func(appDir string) { Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) @@ -78,7 +83,7 @@ var _ = Describe("plugin API", func() { Describe("GetApps", func() { var appName1, appName2 string BeforeEach(func() { - createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() appName1 = helpers.PrefixedRandomName("APP") helpers.WithHelloWorldApp(func(appDir string) { Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) @@ -97,29 +102,35 @@ var _ = Describe("plugin API", func() { Describe("GetCurrentOrg", func() { It("gets the current targeted org", func() { - org, _ := createTargetedOrgAndSpace() - confirmTestPluginOutput("GetCurrentOrg", org) + orgName, _ = createTargetedOrgAndSpace() + confirmTestPluginOutput("GetCurrentOrg", orgName) }) }) Describe("GetCurrentSpace", func() { It("gets the current targeted Space", func() { - _, space := createTargetedOrgAndSpace() + var space string + orgName, space = createTargetedOrgAndSpace() confirmTestPluginOutput("GetCurrentSpace", space) }) }) Describe("GetOrg", func() { It("gets the given org", func() { - org, _ := createTargetedOrgAndSpace() - confirmTestPluginOutputWithArg("GetOrg", org, org) + orgName, _ = createTargetedOrgAndSpace() + confirmTestPluginOutputWithArg("GetOrg", orgName, orgName) }) }) Describe("GetOrgs", func() { + var org1, org2 string + AfterEach(func() { + helpers.QuickDeleteOrg(org1) + helpers.QuickDeleteOrg(org2) + }) It("gets information for multiple orgs", func() { - org1, _ := createTargetedOrgAndSpace() - org2, _ := createTargetedOrgAndSpace() + org1, _ = createTargetedOrgAndSpace() + org2, _ = createTargetedOrgAndSpace() orgNameRegexp := fmt.Sprintf("(?:%s|%s)", org1, org2) confirmTestPluginOutput("GetOrgs", orgNameRegexp, orgNameRegexp) }) @@ -127,17 +138,17 @@ var _ = Describe("plugin API", func() { Describe("GetOrgUsers", func() { It("returns the org users", func() { - org, _ := createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() username, _ := helpers.GetCredentials() - confirmTestPluginOutputWithArg("GetOrgUsers", org, username) + confirmTestPluginOutputWithArg("GetOrgUsers", orgName, username) }) }) Describe("GetOrgUsers", func() { It("returns the org users", func() { - org, _ := createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() username, _ := helpers.GetCredentials() - confirmTestPluginOutputWithArg("GetOrgUsers", org, username) + confirmTestPluginOutputWithArg("GetOrgUsers", orgName, username) }) }) @@ -148,7 +159,7 @@ var _ = Describe("plugin API", func() { broker *servicebrokerstub.ServiceBrokerStub ) BeforeEach(func() { - createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() serviceInstance1 = helpers.PrefixedRandomName("SI1") serviceInstance2 = helpers.PrefixedRandomName("SI2") @@ -172,7 +183,8 @@ var _ = Describe("plugin API", func() { Describe("GetSpace", func() { It("gets the given space", func() { - _, space := createTargetedOrgAndSpace() + var space string + orgName, space = createTargetedOrgAndSpace() confirmTestPluginOutputWithArg("GetSpace", space, space) }) }) @@ -181,7 +193,7 @@ var _ = Describe("plugin API", func() { var space1, space2 string BeforeEach(func() { - _, space1 = createTargetedOrgAndSpace() + orgName, space1 = createTargetedOrgAndSpace() space2 = helpers.NewSpaceName() helpers.CreateSpace(space2) }) @@ -195,8 +207,9 @@ var _ = Describe("plugin API", func() { Describe("GetSpaceUsers", func() { It("returns the space users", func() { username, _ := helpers.GetCredentials() - org, space := createTargetedOrgAndSpace() - session := helpers.CF("GetSpaceUsers", org, space) + var space string + orgName, space = createTargetedOrgAndSpace() + session := helpers.CF("GetSpaceUsers", orgName, space) Eventually(session).Should(Say(username)) Eventually(session).Should(Exit(0)) }) @@ -210,14 +223,14 @@ var _ = Describe("plugin API", func() { Describe("HasOrganization", func() { It("returns true", func() { - createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() confirmTestPluginOutput("HasOrganization", "true") }) }) Describe("HasSpace", func() { It("returns true", func() { - createTargetedOrgAndSpace() + orgName, _ = createTargetedOrgAndSpace() confirmTestPluginOutput("HasSpace", "true") }) }) diff --git a/integration/v7/global/running_security_groups_command_test.go b/integration/v7/global/running_security_groups_command_test.go index e253e821d98..fe8b1cd267e 100644 --- a/integration/v7/global/running_security_groups_command_test.go +++ b/integration/v7/global/running_security_groups_command_test.go @@ -70,6 +70,7 @@ var _ = Describe("running-security-groups command", func() { AfterEach(func() { helpers.DeleteSecurityGroup(securityGroup) + helpers.QuickDeleteOrg(orgName) }) It("displays the globally enabled running security groups exits 0", func() { diff --git a/integration/v7/global/set_space_role_command_test.go b/integration/v7/global/set_space_role_command_test.go index 9e2f99df4e2..aa203a6c046 100644 --- a/integration/v7/global/set_space_role_command_test.go +++ b/integration/v7/global/set_space_role_command_test.go @@ -26,6 +26,7 @@ var _ = Describe("set-space-role command", func() { AfterEach(func() { helpers.EnableFeatureFlag("set_roles_by_username") + helpers.QuickDeleteOrg(orgName) }) When("the user does not exist", func() { diff --git a/integration/v7/global/staging_security_groups_command_test.go b/integration/v7/global/staging_security_groups_command_test.go index 49049c28379..280512a3b03 100644 --- a/integration/v7/global/staging_security_groups_command_test.go +++ b/integration/v7/global/staging_security_groups_command_test.go @@ -70,6 +70,7 @@ var _ = Describe("staging-security-groups command", func() { AfterEach(func() { helpers.DeleteSecurityGroup(securityGroup) + helpers.QuickDeleteOrg(orgName) }) It("displays the globally enabled staging security groups exits 0", func() { diff --git a/integration/v7/isolated/create_space_quota_command_test.go b/integration/v7/isolated/create_space_quota_command_test.go index 424023515df..048547566ac 100644 --- a/integration/v7/isolated/create_space_quota_command_test.go +++ b/integration/v7/isolated/create_space_quota_command_test.go @@ -60,6 +60,10 @@ var _ = Describe("create-space-quota command", func() { spaceQuotaName = helpers.QuotaName() }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + When("the quota name is not provided", func() { It("tells the user that the quota name is required, prints help text, and exits 1", func() { session := helpers.CF("create-space-quota") diff --git a/integration/v7/isolated/move_route_command_test.go b/integration/v7/isolated/move_route_command_test.go index 242871705a0..2ea4a7c6b1f 100644 --- a/integration/v7/isolated/move_route_command_test.go +++ b/integration/v7/isolated/move_route_command_test.go @@ -147,6 +147,8 @@ var _ = Describe("move route command", func() { AfterEach(func() { domain.DeleteShared() + helpers.QuickDeleteOrg(targetOrgName) + helpers.QuickDeleteOrg(orgName) }) It("Transfers ownership of the route to the destination space", func() { diff --git a/integration/v7/isolated/org_users_command_test.go b/integration/v7/isolated/org_users_command_test.go index f2f6ec63871..f013da9db1b 100644 --- a/integration/v7/isolated/org_users_command_test.go +++ b/integration/v7/isolated/org_users_command_test.go @@ -40,6 +40,10 @@ var _ = Describe("org-users command", func() { helpers.CreateOrg(orgName) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + When("the target org has multiple users with different roles", func() { var ( orgManagerUser string diff --git a/integration/v7/isolated/rename_org_command_test.go b/integration/v7/isolated/rename_org_command_test.go index ad5accf8993..e8bb88ecbb0 100644 --- a/integration/v7/isolated/rename_org_command_test.go +++ b/integration/v7/isolated/rename_org_command_test.go @@ -107,6 +107,10 @@ var _ = Describe("rename-org command", func() { helpers.CreateOrg(orgNameNew) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgNameNew) + }) + It("fails to rename the org", func() { session := helpers.CF("rename-org", orgName, orgNameNew) userName, _ := helpers.GetCredentials() diff --git a/integration/v7/isolated/scale_command_test.go b/integration/v7/isolated/scale_command_test.go index 1774c1c39a8..dbfc9af9cf2 100644 --- a/integration/v7/isolated/scale_command_test.go +++ b/integration/v7/isolated/scale_command_test.go @@ -105,10 +105,10 @@ var _ = Describe("scale command", func() { helpers.WithProcfileApp(func(appDir string) { Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName)).Should(Exit(0)) }) - helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "1G") + helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "256M") }) - When("scale option flags are not provided", func() { + XWhen("scale option flags are not provided", func() { It("displays the current scale properties for all processes", func() { session := helpers.CF("scale", appName) @@ -162,7 +162,7 @@ var _ = Describe("scale command", func() { Consistently(session).ShouldNot(Say("Stopping")) Consistently(session).ShouldNot(Say("Starting")) - helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, true, "1G") + helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, true, "256M") session = helpers.CF("app", appName) Eventually(session).Should(Exit(0)) @@ -179,7 +179,17 @@ var _ = Describe("scale command", func() { }) }) - When("Scaling the memory", func() { + When("-f flag provided", func() { + It("scales without prompt", func() { + session := helpers.CF("scale", appName, "-m", "64M", "-f") + Eventually(session).Should(Exit(0)) + Expect(session).To(Say("Scaling app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName)) + + helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "64M") + }) + }) + + XWhen("Scaling the memory", func() { It("scales memory to 64M", func() { buffer := NewBuffer() _, err := buffer.Write([]byte("y\n")) @@ -194,7 +204,7 @@ var _ = Describe("scale command", func() { helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "64M") }) - When("-f flag provided", func() { + XWhen("-f flag provided", func() { It("scales without prompt", func() { session := helpers.CF("scale", appName, "-m", "64M", "-f") Eventually(session).Should(Exit(0)) @@ -205,7 +215,7 @@ var _ = Describe("scale command", func() { }) }) - When("Scaling the disk space", func() { + XWhen("Scaling the disk space", func() { It("scales disk to 512M", func() { buffer := NewBuffer() _, err := buffer.Write([]byte("y\n")) @@ -221,7 +231,7 @@ var _ = Describe("scale command", func() { helpers.WaitForAppDiskToTakeEffect(appName, 0, 0, false, "512M") }) - When("-f flag provided", func() { + XWhen("-f flag provided", func() { It("scales without prompt", func() { session := helpers.CF("scale", appName, "-k", "512M", "-f") Eventually(session).Should(Exit(0)) @@ -232,7 +242,7 @@ var _ = Describe("scale command", func() { }) }) - When("Scaling the log rate limit", func() { + XWhen("Scaling the log rate limit", func() { BeforeEach(func() { helpers.SkipIfVersionLessThan(ccversion.MinVersionLogRateLimitingV3) }) @@ -252,7 +262,7 @@ var _ = Describe("scale command", func() { helpers.WaitForLogRateLimitToTakeEffect(appName, 0, 0, false, "1M") }) - When("-f flag provided", func() { + XWhen("-f flag provided", func() { It("scales without prompt", func() { session := helpers.CF("scale", appName, "-l", "1M", "-f") Eventually(session).Should(Exit(0)) diff --git a/integration/v7/isolated/security_groups_command_test.go b/integration/v7/isolated/security_groups_command_test.go index 8581aa8f1db..ed2538be128 100644 --- a/integration/v7/isolated/security_groups_command_test.go +++ b/integration/v7/isolated/security_groups_command_test.go @@ -118,6 +118,7 @@ var _ = Describe("security-groups command", func() { helpers.DeleteSecurityGroup(securityGroup3) helpers.DeleteSecurityGroup(securityGroup4) helpers.DeleteSecurityGroup(securityGroup5) + helpers.QuickDeleteOrg(orgName) }) It("displays the security groups exits 0", func() { diff --git a/integration/v7/isolated/services_command_test.go b/integration/v7/isolated/services_command_test.go index 6afe49ffa03..a04819006df 100644 --- a/integration/v7/isolated/services_command_test.go +++ b/integration/v7/isolated/services_command_test.go @@ -163,11 +163,11 @@ var _ = Describe("services command", func() { Context("has shared service instances", func() { var ( - managedService, appNameOnSpaceA, appNameOnSpaceB string + managedService, appNameOnSpaceA, appNameOnSpaceB, orgName string ) BeforeEach(func() { - orgName := helpers.NewOrgName() + orgName = helpers.NewOrgName() spaceA := helpers.NewSpaceName() spaceB := helpers.NewSpaceName() managedService = helpers.PrefixedRandomName("MANAGED1") @@ -193,6 +193,10 @@ var _ = Describe("services command", func() { helpers.TargetOrgAndSpace(orgName, spaceA) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + It("should not output bound apps in the shared spaces", func() { session := helpers.CF(command) Eventually(session).Should(Exit(0)) diff --git a/integration/v7/isolated/share_private_domain_test.go b/integration/v7/isolated/share_private_domain_test.go index e9e62700353..f6c416fdb6b 100644 --- a/integration/v7/isolated/share_private_domain_test.go +++ b/integration/v7/isolated/share_private_domain_test.go @@ -58,6 +58,11 @@ var _ = Describe("share-private-domain command", func() { domain.CreatePrivate() }) + AfterEach(func() { + helpers.QuickDeleteOrg(sharedWithOrgName) + helpers.QuickDeleteOrg(orgName) + }) + It("should create the shared domain", func() { session := helpers.CF("share-private-domain", sharedWithOrgName, domainName) diff --git a/integration/v7/isolated/share_route_command_test.go b/integration/v7/isolated/share_route_command_test.go index 8697ac71e95..5c5e6369916 100644 --- a/integration/v7/isolated/share_route_command_test.go +++ b/integration/v7/isolated/share_route_command_test.go @@ -147,6 +147,7 @@ var _ = Describe("share route command", func() { AfterEach(func() { domain.Delete() + helpers.QuickDeleteOrg(targetOrgName) }) It("shared the route to the destination space", func() { diff --git a/integration/v7/isolated/space_quota_command_test.go b/integration/v7/isolated/space_quota_command_test.go index 99203a033b3..e2c7094f954 100644 --- a/integration/v7/isolated/space_quota_command_test.go +++ b/integration/v7/isolated/space_quota_command_test.go @@ -49,6 +49,10 @@ var _ = Describe("space-quota command", func() { helpers.TargetOrg(orgName) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + When("the quota does not exist", func() { It("displays quota not found and exits 1", func() { session := helpers.CF("space-quota", quotaName) diff --git a/integration/v7/isolated/space_users_command_test.go b/integration/v7/isolated/space_users_command_test.go index 2932a3af070..f2d594aaf24 100644 --- a/integration/v7/isolated/space_users_command_test.go +++ b/integration/v7/isolated/space_users_command_test.go @@ -42,6 +42,10 @@ var _ = Describe("space-users command", func() { helpers.CreateOrgAndSpace(orgName, spaceName) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + When("the target space has multiple users with different roles", func() { var ( spaceManagerUser string diff --git a/integration/v7/isolated/spaces_command_test.go b/integration/v7/isolated/spaces_command_test.go index 5ae047e821c..540c7da5d0d 100644 --- a/integration/v7/isolated/spaces_command_test.go +++ b/integration/v7/isolated/spaces_command_test.go @@ -60,6 +60,10 @@ var _ = Describe("spaces command", func() { helpers.CreateSpace(spaceName6) }) + AfterEach(func() { + helpers.QuickDeleteOrg(orgName) + }) + When("the --labels flag is given", func() { BeforeEach(func() { diff --git a/integration/v7/isolated/start_command_test.go b/integration/v7/isolated/start_command_test.go index 6a6403c564a..0e0b9cafb39 100644 --- a/integration/v7/isolated/start_command_test.go +++ b/integration/v7/isolated/start_command_test.go @@ -128,7 +128,7 @@ var _ = Describe("start command", func() { Eventually(session).Should(Say(`routes:\s+%s.%s`, appName, helpers.DefaultSharedDomain())) Eventually(session).Should(Say(`type:\s+web`)) Eventually(session).Should(Say(`instances:\s+1/1`)) - Eventually(session).Should(Say(`memory usage:\s+1024M`)) + Eventually(session).Should(Say(`memory usage:\s+256M`)) Eventually(session).Should(Say(`\s+state\s+since\s+cpu\s+memory\s+disk\s+logging\s+cpu entitlement\s+details`)) Eventually(session).Should(Say(`#0\s+(starting|running)\s+\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z`)) diff --git a/integration/v7/isolated/unshare_private_domain_test.go b/integration/v7/isolated/unshare_private_domain_test.go index aa30eea5552..638cacff0c8 100644 --- a/integration/v7/isolated/unshare_private_domain_test.go +++ b/integration/v7/isolated/unshare_private_domain_test.go @@ -70,6 +70,10 @@ var _ = Describe("unshare-private-domain command", func() { domain.V7Share(sharedToOrgName) }) + AfterEach(func() { + helpers.QuickDeleteOrg(sharedToOrgName) + }) + It("unshares the domain from the org", func() { buffer := NewBuffer() _, err := buffer.Write([]byte("y\n")) @@ -98,6 +102,10 @@ var _ = Describe("unshare-private-domain command", func() { domain.V7Share(sharedToOrgName) }) + AfterEach(func() { + helpers.QuickDeleteOrg(sharedToOrgName) + }) + It("does not unshare the domain from the org", func() { buffer := NewBuffer() _, err := buffer.Write([]byte("n\n")) diff --git a/integration/v7/isolated/unshare_route_command_test.go b/integration/v7/isolated/unshare_route_command_test.go index 8520edf2b5f..ce745ec5001 100644 --- a/integration/v7/isolated/unshare_route_command_test.go +++ b/integration/v7/isolated/unshare_route_command_test.go @@ -152,6 +152,7 @@ var _ = Describe("unshare route command", func() { AfterEach(func() { domain.Delete() + helpers.QuickDeleteOrg(targetOrgName) }) It("unshared the route from the intended space", func() { From d724fb797cb4c34e894a2fe5460962c986f3c663 Mon Sep 17 00:00:00 2001 From: AL Berez Date: Wed, 30 Oct 2024 07:36:44 -0700 Subject: [PATCH 02/21] Specify CFD version in integration tests workflow (#3273) This allows to lock CFD in case incompatible changes in the latest release. --- .github/workflows/tests-integration.yml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 0961b74dccd..5fb522b4e1d 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -38,6 +38,10 @@ on: description: Pre-provisioned environment lease namespace to use in tests required: false type: string + cfd_version: + description: Use specific version of CFD. Leave empty to use latest. + default: "" + type: string run_unit_tests: description: Run unit tests required: false @@ -132,18 +136,24 @@ jobs: template_namespace: ${{ vars.SHEPHERD_TEMPLATE_NAMESPACE || 'official' }} lease_duration: ${{ vars.SHEPHERD_LEASE_DURATION || '8h' }} lease_namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} + cfd_version: ${{ inputs.cfd_version || vars.CFD_VERSION || '' }} run: | shepherd login service-account ${account_token} if [[ -z $SHEPHERD_LEASE_ID ]]; then if [ -z "$template_argument" ]; then - export template_argument='{"gcp_region": "us-west2", - "vm_type": "n1-standard-8", - "root_disk_gb": 32, - "disk_pool_gb": 150, - "cfd_version": "", - "additional_opsfiles_b64": ""}' + export template_argument=$(cat < Date: Mon, 4 Nov 2024 15:08:39 -0600 Subject: [PATCH 03/21] Fix linter again v8 (#3286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix linter with multiple main package inside the same folder * Bump version of golangci-lint used * Fix workflow to ensure units run by default before integration Signed-off-by: João Pereira --- .github/workflows/golangci-lint.yml | 2 +- .github/workflows/tests-integration.yml | 6 ++-- .gitignore | 6 ++-- Makefile | 4 +-- cf/commands/plugin/install_plugin_test.go | 21 +++++++------ cf/commands/plugin/plugin_suite_test.go | 18 +++++------ cf/commands/plugin/plugins_test.go | 4 +-- cf/commands/plugin/uninstall_plugin_test.go | 7 ++--- .../pluginconfig/plugin_config_test.go | 6 ++-- command/v7/v7_suite_test.go | 2 +- .../.cf/plugins/config.json | 4 +-- .../plugin-config/.cf/plugins/config.json | 4 +-- .../{ => alias_conflicts}/alias_conflicts.go | 0 .../{ => call_core_cmd}/call_core_cmd.go | 0 .../{ => empty_plugin}/empty_plugin.go | 0 fixtures/plugins/{ => input}/input.go | 0 fixtures/plugins/{ => my_say}/my_say.go | 0 fixtures/plugins/{ => panics}/panics.go | 0 fixtures/plugins/{ => test_1}/test_1.go | 0 fixtures/plugins/{ => test_2}/test_2.go | 0 .../{ => test_with_help}/test_with_help.go | 0 .../{ => test_with_orgs}/test_with_orgs.go | 0 .../test_with_orgs_short_name.go | 0 .../{ => test_with_push}/test_with_push.go | 0 .../test_with_push_short_name.go | 0 integration/helpers/curl.go | 4 +-- integration/helpers/route.go | 4 +-- integration/helpers/version.go | 2 +- integration/v7/isolated/app_command_test.go | 2 +- .../bind_route_service_command_test.go | 6 ++-- .../v7/isolated/bind_service_command_test.go | 4 +-- .../create_service_key_command_test.go | 4 +-- .../unbind_route_service_command_test.go | 2 +- .../isolated/unbind_service_command_test.go | 2 +- integration/v7/push/droplet_flag_test.go | 6 ++-- plugin/plugin_examples/README.md | 30 +++++++++---------- .../{ => basic_plugin}/basic_plugin.go | 0 plugin/plugin_examples/{ => echo}/echo.go | 0 .../{ => interactive}/interactive.go | 0 .../multiple_commands.go | 0 plugin/plugin_shim_test.go | 2 +- plugin/plugin_suite_test.go | 2 +- 42 files changed, 76 insertions(+), 78 deletions(-) rename fixtures/plugins/{ => alias_conflicts}/alias_conflicts.go (100%) rename fixtures/plugins/{ => call_core_cmd}/call_core_cmd.go (100%) rename fixtures/plugins/{ => empty_plugin}/empty_plugin.go (100%) rename fixtures/plugins/{ => input}/input.go (100%) rename fixtures/plugins/{ => my_say}/my_say.go (100%) rename fixtures/plugins/{ => panics}/panics.go (100%) rename fixtures/plugins/{ => test_1}/test_1.go (100%) rename fixtures/plugins/{ => test_2}/test_2.go (100%) rename fixtures/plugins/{ => test_with_help}/test_with_help.go (100%) rename fixtures/plugins/{ => test_with_orgs}/test_with_orgs.go (100%) rename fixtures/plugins/{ => test_with_orgs_short_name}/test_with_orgs_short_name.go (100%) rename fixtures/plugins/{ => test_with_push}/test_with_push.go (100%) rename fixtures/plugins/{ => test_with_push_short_name}/test_with_push_short_name.go (100%) rename plugin/plugin_examples/{ => basic_plugin}/basic_plugin.go (100%) rename plugin/plugin_examples/{ => echo}/echo.go (100%) rename plugin/plugin_examples/{ => interactive}/interactive.go (100%) rename plugin/plugin_examples/{ => multiple_commands}/multiple_commands.go (100%) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 88b0b530f53..7cd276f1f8a 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -37,7 +37,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: - version: v1.58 + version: v1.61 args: -v --exclude-dirs cf --exclude-dirs fixtures --exclude-dirs plugin --exclude-dirs command/plugin format: name: Run go fmt diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 5fb522b4e1d..0a67252b7c5 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -96,17 +96,17 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - if: ${{ inputs.run_unit_tests == 'true' }} + if: ${{ inputs.run_unit_tests }} with: ref: ${{needs.get-sha.outputs.gitRef}} - name: Set Up Go uses: actions/setup-go@v5 - if: ${{ inputs.run_unit_tests == 'true' }} + if: ${{ inputs.run_unit_tests }} with: go-version-file: go.mod check-latest: true - name: Run Units - if: ${{ inputs.run_unit_tests == 'true' }} + if: ${{ inputs.run_unit_tests }} run: make units claim-env: diff --git a/.gitignore b/.gitignore index cc14c3edb44..a35518518ec 100644 --- a/.gitignore +++ b/.gitignore @@ -57,9 +57,9 @@ tmp/ fixtures/.cf #Compiled Plugins -fixtures/plugins/test_1 -fixtures/plugins/test_2 -fixtures/plugins/empty_plugin +fixtures/plugins/test_1/test_1 +fixtures/plugins/test_2/test_2 +fixtures/plugins/empty_plugin/empty_plugin fixtures/config/plugin-config/.cf/plugins/test_1 fixtures/config/plugin-config/.cf/plugins/test_2 fixtures/config/plugin-config/.cf/plugins/empty_plugin diff --git a/Makefile b/Makefile index 409563d4dec..fca5f3607dd 100644 --- a/Makefile +++ b/Makefile @@ -202,13 +202,13 @@ units-plugin: install-test-deps ifeq ($(OS),Windows_NT) units-non-plugin: install-test-deps - @rm -f $(wildcard fixtures/plugins/*.exe) + @rm -f $(wildcard fixtures/plugins/*/*.exe) @ginkgo version CF_HOME=$(CURDIR)/fixtures CF_USERNAME="" CF_PASSWORD="" $(ginkgo_units) \ -skip-package integration,plugin,cf\actors\plugin,cf\commands\plugin,cf\actors\plugin,util\randomword else units-non-plugin: install-test-deps - @rm -f $(wildcard fixtures/plugins/*.exe) + @rm -f $(wildcard fixtures/plugins/*/*.exe) @ginkgo version CF_HOME=$(CURDIR)/fixtures CF_USERNAME="" CF_PASSWORD="" $(ginkgo_units) \ -skip-package integration,plugin,cf/actors/plugin,cf/commands/plugin,cf/actors/plugin,util/randomword diff --git a/cf/commands/plugin/install_plugin_test.go b/cf/commands/plugin/install_plugin_test.go index ca8df3139e3..d0913e59874 100644 --- a/cf/commands/plugin/install_plugin_test.go +++ b/cf/commands/plugin/install_plugin_test.go @@ -2,7 +2,6 @@ package plugin_test import ( "fmt" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -80,15 +79,15 @@ var _ = Describe("Install", func() { if err != nil { panic(err) } - test_1 = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_1.exe") - test_2 = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_2.exe") + test_1 = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_1", "test_1.exe") + test_2 = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_2", "test_2.exe") test_curDir = filepath.Join("test_1.exe") - test_with_help = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_with_help.exe") - test_with_orgs = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_with_orgs.exe") - test_with_orgs_short_name = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_with_orgs_short_name.exe") - aliasConflicts = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "alias_conflicts.exe") + test_with_help = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_with_help", "test_with_help.exe") + test_with_orgs = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_with_orgs", "test_with_orgs.exe") + test_with_orgs_short_name = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "test_with_orgs_short_name", "test_with_orgs_short_name.exe") + aliasConflicts = filepath.Join(dir, "..", "..", "..", "fixtures", "plugins", "alias_conflicts", "alias_conflicts.exe") - homeDir, err = ioutil.TempDir(os.TempDir(), "plugins") + homeDir, err = os.MkdirTemp(os.TempDir(), "plugins") Expect(err).ToNot(HaveOccurred()) pluginDir = filepath.Join(homeDir, ".cf", "plugins") @@ -96,7 +95,7 @@ var _ = Describe("Install", func() { curDir, err = os.Getwd() Expect(err).ToNot(HaveOccurred()) - pluginFile, err = ioutil.TempFile("./", "test_plugin") + pluginFile, err = os.CreateTemp("./", "test_plugin") Expect(err).ToNot(HaveOccurred()) if runtime.GOOS != "windows" { @@ -541,7 +540,7 @@ var _ = Describe("Install", func() { runCommand(filepath.Join(curDir, pluginFile.Name()), "-f") Expect(ui.Outputs()).To(ContainSubstrings( []string{"Installing plugin"}, - []string{"The file", pluginFile.Name(), "already exists"}, + []string{"The file", filepath.Clean(pluginFile.Name()), "already exists"}, []string{"FAILED"}, )) }) @@ -559,7 +558,7 @@ var _ = Describe("Install", func() { curDir, err := os.Getwd() Expect(err).ToNot(HaveOccurred()) - err = os.Chdir("../../../fixtures/plugins") + err = os.Chdir("../../../fixtures/plugins/test_1") Expect(err).ToNot(HaveOccurred()) runCommand(test_curDir, "-f") diff --git a/cf/commands/plugin/plugin_suite_test.go b/cf/commands/plugin/plugin_suite_test.go index c970694347c..b3609ae1eb2 100644 --- a/cf/commands/plugin/plugin_suite_test.go +++ b/cf/commands/plugin/plugin_suite_test.go @@ -21,15 +21,15 @@ func TestPlugin(t *testing.T) { RegisterFailHandler(Fail) - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_with_help") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_with_orgs") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_with_orgs_short_name") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_with_push") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_with_push_short_name") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_1") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "test_2") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "empty_plugin") - pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins"), "alias_conflicts") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_with_help"), "test_with_help") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_with_orgs"), "test_with_orgs") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_with_orgs_short_name"), "test_with_orgs_short_name") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_with_push"), "test_with_push") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_with_push_short_name"), "test_with_push_short_name") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_1"), "test_1") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "test_2"), "test_2") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "empty_plugin"), "empty_plugin") + pluginbuilder.BuildTestBinary(filepath.Join("..", "..", "..", "fixtures", "plugins", "alias_conflicts"), "alias_conflicts") RunSpecs(t, "Plugin Suite") } diff --git a/cf/commands/plugin/plugins_test.go b/cf/commands/plugin/plugins_test.go index 3f9caea8fd0..d9634b02190 100644 --- a/cf/commands/plugin/plugins_test.go +++ b/cf/commands/plugin/plugins_test.go @@ -48,7 +48,7 @@ var _ = Describe("Plugins", func() { It("computes and prints the sha1 checksum of the binary", func() { config.PluginsReturns(map[string]pluginconfig.PluginMetadata{ "Test1": { - Location: "../../../fixtures/plugins/test_1.go", + Location: "../../../fixtures/plugins/test_1/test_1.go", Version: plugin.VersionType{Major: 1, Minor: 2, Build: 3}, Commands: []plugin.Command{ {Name: "test_1_cmd1", HelpText: "help text for test_1_cmd1"}, @@ -157,7 +157,7 @@ var _ = Describe("Plugins", func() { It("does not list the plugin when it provides no available commands", func() { config.PluginsReturns(map[string]pluginconfig.PluginMetadata{ - "EmptyPlugin": {Location: "../../../fixtures/plugins/empty_plugin.exe"}, + "EmptyPlugin": {Location: "../../../fixtures/plugins/empty_plugin/empty_plugin.exe"}, }) runCommand() diff --git a/cf/commands/plugin/uninstall_plugin_test.go b/cf/commands/plugin/uninstall_plugin_test.go index eccf500ad65..2060faa3565 100644 --- a/cf/commands/plugin/uninstall_plugin_test.go +++ b/cf/commands/plugin/uninstall_plugin_test.go @@ -1,7 +1,6 @@ package plugin_test import ( - "io/ioutil" "os" "path/filepath" @@ -41,7 +40,7 @@ var _ = Describe("Uninstall", func() { requirementsFactory = new(requirementsfakes.FakeFactory) var err error - fakePluginRepoDir, err = ioutil.TempDir("", "plugins") + fakePluginRepoDir, err = os.MkdirTemp("", "plugins") Expect(err).ToNot(HaveOccurred()) fixtureDir := filepath.Join("..", "..", "..", "fixtures", "plugins") @@ -50,8 +49,8 @@ var _ = Describe("Uninstall", func() { err = os.MkdirAll(pluginDir, 0700) Expect(err).NotTo(HaveOccurred()) - fileutils.CopyPathToPath(filepath.Join(fixtureDir, "test_1.exe"), filepath.Join(pluginDir, "test_1.exe")) - fileutils.CopyPathToPath(filepath.Join(fixtureDir, "test_2.exe"), filepath.Join(pluginDir, "test_2.exe")) + fileutils.CopyPathToPath(filepath.Join(fixtureDir, "test_1", "test_1.exe"), filepath.Join(pluginDir, "test_1.exe")) + fileutils.CopyPathToPath(filepath.Join(fixtureDir, "test_2", "test_2.exe"), filepath.Join(pluginDir, "test_2.exe")) confighelpers.PluginRepoDir = func() string { return fakePluginRepoDir diff --git a/cf/configuration/pluginconfig/plugin_config_test.go b/cf/configuration/pluginconfig/plugin_config_test.go index ffc259781be..2b7c0b84547 100644 --- a/cf/configuration/pluginconfig/plugin_config_test.go +++ b/cf/configuration/pluginconfig/plugin_config_test.go @@ -83,7 +83,7 @@ var _ = Describe("PluginConfig", func() { } metadata = PluginMetadata{ - Location: "../../../fixtures/plugins/test_1.exe", + Location: "../../../fixtures/plugins/test_1/test_1.exe", Commands: commands1, } }) @@ -110,9 +110,9 @@ var _ = Describe("PluginConfig", func() { }) It("returns a list of plugin executables and their location", func() { - Expect(plugins["Test1"].Location).To(Equal("../../../fixtures/plugins/test_1.exe")) + Expect(plugins["Test1"].Location).To(Equal("../../../fixtures/plugins/test_1/test_1.exe")) Expect(plugins["Test1"].Commands).To(Equal(commands1)) - Expect(plugins["Test2"].Location).To(Equal("../../../fixtures/plugins/test_2.exe")) + Expect(plugins["Test2"].Location).To(Equal("../../../fixtures/plugins/test_2/test_2.exe")) Expect(plugins["Test2"].Commands).To(Equal(commands2)) }) }) diff --git a/command/v7/v7_suite_test.go b/command/v7/v7_suite_test.go index 0095f28f9a1..8a1af2c03a2 100644 --- a/command/v7/v7_suite_test.go +++ b/command/v7/v7_suite_test.go @@ -74,7 +74,7 @@ func setFlag(cmd interface{}, flag string, values ...interface{}) { case value.Type().ConvertibleTo(field.Type): val.Field(i).Set(value.Convert(field.Type)) return - case reflect.PtrTo(field.Type).Implements(reflect.TypeOf((*interface{ UnmarshalFlag(string) error })(nil)).Elem()): + case reflect.PointerTo(field.Type).Implements(reflect.TypeOf((*interface{ UnmarshalFlag(string) error })(nil)).Elem()): elem := reflect.New(field.Type) e := elem.MethodByName("UnmarshalFlag").Call([]reflect.Value{value}) if !e[0].IsNil() { diff --git a/fixtures/config/help-plugin-test-config/.cf/plugins/config.json b/fixtures/config/help-plugin-test-config/.cf/plugins/config.json index acd96407dca..d37ebc91b07 100644 --- a/fixtures/config/help-plugin-test-config/.cf/plugins/config.json +++ b/fixtures/config/help-plugin-test-config/.cf/plugins/config.json @@ -1,14 +1,14 @@ { "Plugins": { "Test1":{ - "Location":"../../fixtures/plugins/test_1.exe", + "Location":"../../fixtures/plugins/test_1/test_1.exe", "Commands":[ {"Name":"test1_cmd1","Alias":"test1_cmd1_alias","HelpText":"help text for test1 cmd1"}, {"Name":"test1_cmd2","HelpText":"help text for test1 cmd2"} ] }, "Test2":{ - "Location":"../../fixtures/plugins/test_2.exe", + "Location":"../../fixtures/plugins/test_2/test_2.exe", "Commands":[ {"Name":"test2_cmd1","Alias":"tc1","HelpText":"help text for test2 cmd1"}, {"Name":"test2_cmd2","HelpText":"help text for test2 cmd2"}, diff --git a/fixtures/config/plugin-config/.cf/plugins/config.json b/fixtures/config/plugin-config/.cf/plugins/config.json index b039625b481..b4234c8887c 100644 --- a/fixtures/config/plugin-config/.cf/plugins/config.json +++ b/fixtures/config/plugin-config/.cf/plugins/config.json @@ -1,14 +1,14 @@ { "Plugins": { "Test1":{ - "Location":"../../../fixtures/plugins/test_1.exe", + "Location":"../../../fixtures/plugins/test_1/test_1.exe", "Commands":[ {"Name":"test_1_cmd1","HelpText":"help text for test1 cmd1"}, {"Name":"test_1_cmd2","HelpText":"help text for test1 cmd2"} ] }, "Test2":{ - "Location":"../../../fixtures/plugins/test_2.exe", + "Location":"../../../fixtures/plugins/test_2/test_2.exe", "Commands":[ {"Name":"test_2_cmd1","HelpText":"help text for test2 cmd1"}, {"Name":"test_2_cmd2","HelpText":"help text for test2 cmd2"} diff --git a/fixtures/plugins/alias_conflicts.go b/fixtures/plugins/alias_conflicts/alias_conflicts.go similarity index 100% rename from fixtures/plugins/alias_conflicts.go rename to fixtures/plugins/alias_conflicts/alias_conflicts.go diff --git a/fixtures/plugins/call_core_cmd.go b/fixtures/plugins/call_core_cmd/call_core_cmd.go similarity index 100% rename from fixtures/plugins/call_core_cmd.go rename to fixtures/plugins/call_core_cmd/call_core_cmd.go diff --git a/fixtures/plugins/empty_plugin.go b/fixtures/plugins/empty_plugin/empty_plugin.go similarity index 100% rename from fixtures/plugins/empty_plugin.go rename to fixtures/plugins/empty_plugin/empty_plugin.go diff --git a/fixtures/plugins/input.go b/fixtures/plugins/input/input.go similarity index 100% rename from fixtures/plugins/input.go rename to fixtures/plugins/input/input.go diff --git a/fixtures/plugins/my_say.go b/fixtures/plugins/my_say/my_say.go similarity index 100% rename from fixtures/plugins/my_say.go rename to fixtures/plugins/my_say/my_say.go diff --git a/fixtures/plugins/panics.go b/fixtures/plugins/panics/panics.go similarity index 100% rename from fixtures/plugins/panics.go rename to fixtures/plugins/panics/panics.go diff --git a/fixtures/plugins/test_1.go b/fixtures/plugins/test_1/test_1.go similarity index 100% rename from fixtures/plugins/test_1.go rename to fixtures/plugins/test_1/test_1.go diff --git a/fixtures/plugins/test_2.go b/fixtures/plugins/test_2/test_2.go similarity index 100% rename from fixtures/plugins/test_2.go rename to fixtures/plugins/test_2/test_2.go diff --git a/fixtures/plugins/test_with_help.go b/fixtures/plugins/test_with_help/test_with_help.go similarity index 100% rename from fixtures/plugins/test_with_help.go rename to fixtures/plugins/test_with_help/test_with_help.go diff --git a/fixtures/plugins/test_with_orgs.go b/fixtures/plugins/test_with_orgs/test_with_orgs.go similarity index 100% rename from fixtures/plugins/test_with_orgs.go rename to fixtures/plugins/test_with_orgs/test_with_orgs.go diff --git a/fixtures/plugins/test_with_orgs_short_name.go b/fixtures/plugins/test_with_orgs_short_name/test_with_orgs_short_name.go similarity index 100% rename from fixtures/plugins/test_with_orgs_short_name.go rename to fixtures/plugins/test_with_orgs_short_name/test_with_orgs_short_name.go diff --git a/fixtures/plugins/test_with_push.go b/fixtures/plugins/test_with_push/test_with_push.go similarity index 100% rename from fixtures/plugins/test_with_push.go rename to fixtures/plugins/test_with_push/test_with_push.go diff --git a/fixtures/plugins/test_with_push_short_name.go b/fixtures/plugins/test_with_push_short_name/test_with_push_short_name.go similarity index 100% rename from fixtures/plugins/test_with_push_short_name.go rename to fixtures/plugins/test_with_push_short_name/test_with_push_short_name.go diff --git a/integration/helpers/curl.go b/integration/helpers/curl.go index 13a089c8dff..37131bc572a 100644 --- a/integration/helpers/curl.go +++ b/integration/helpers/curl.go @@ -9,10 +9,10 @@ import ( . "github.com/onsi/gomega/gexec" ) -// Curl runs a 'cf curl' command with a URL format string, allowing props to be +// Curlf runs a 'cf curl' command with a URL format string, allowing props to be // interpolated into the URL string with fmt.Sprintf. The JSON response is // unmarshaled into given obj. -func Curl(obj interface{}, url string, props ...interface{}) { +func Curlf(obj interface{}, url string, props ...interface{}) { session := CF("curl", fmt.Sprintf(url, props...)) Eventually(session).Should(Exit(0)) rawJSON := strings.TrimSpace(string(session.Out.Contents())) diff --git a/integration/helpers/route.go b/integration/helpers/route.go index d9ad43c9b12..d4cad8196ae 100644 --- a/integration/helpers/route.go +++ b/integration/helpers/route.go @@ -117,7 +117,7 @@ func (r Route) GUID() string { var domainReceiver struct { Domains []resources.Domain `json:"resources"` } - Curl(&domainReceiver, "/v3/domains?names=%s", r.Domain) + Curlf(&domainReceiver, "/v3/domains?names=%s", r.Domain) Expect(domainReceiver.Domains).To(HaveLen(1)) query := []string{fmt.Sprintf("domain_guids=%s", domainReceiver.Domains[0].GUID)} @@ -138,7 +138,7 @@ func (r Route) GUID() string { var routeReceiver struct { Routes []resources.Route `json:"resources"` } - Curl(&routeReceiver, "/v3/routes?%s", strings.Join(query, "&")) + Curlf(&routeReceiver, "/v3/routes?%s", strings.Join(query, "&")) Expect(routeReceiver.Routes).To(HaveLen(1)) return routeReceiver.Routes[0].GUID diff --git a/integration/helpers/version.go b/integration/helpers/version.go index d299b000f75..40ff10205fa 100644 --- a/integration/helpers/version.go +++ b/integration/helpers/version.go @@ -181,7 +181,7 @@ func SkipIfNoRoutingAPI() { var response struct { RoutingEndpoint string `json:"routing_endpoint"` } - Curl(&response, "/v2/info") + Curlf(&response, "/v2/info") if response.RoutingEndpoint == "" { Skip("Test requires routing endpoint on /v2/info") diff --git a/integration/v7/isolated/app_command_test.go b/integration/v7/isolated/app_command_test.go index c78a72a97ba..e6148783688 100644 --- a/integration/v7/isolated/app_command_test.go +++ b/integration/v7/isolated/app_command_test.go @@ -215,7 +215,7 @@ applications: } `json:"resources"` } - helpers.Curl(&AppInfo, "/v3/apps?names=%s", appName) + helpers.Curlf(&AppInfo, "/v3/apps?names=%s", appName) appGUID = AppInfo.Resources[0].GUID }) diff --git a/integration/v7/isolated/bind_route_service_command_test.go b/integration/v7/isolated/bind_route_service_command_test.go index 939e6312dce..14ab99f21ec 100644 --- a/integration/v7/isolated/bind_route_service_command_test.go +++ b/integration/v7/isolated/bind_route_service_command_test.go @@ -119,7 +119,7 @@ var _ = Describe("bind-route-service command", func() { var receiver struct { Resources []resources.RouteBinding `json:"resources"` } - helpers.Curl(&receiver, "/v3/service_route_bindings?service_instance_names=%s", serviceInstanceName) + helpers.Curlf(&receiver, "/v3/service_route_bindings?service_instance_names=%s", serviceInstanceName) Expect(receiver.Resources).To(HaveLen(1)) return string(receiver.Resources[0].LastOperation.State) @@ -232,11 +232,11 @@ var _ = Describe("bind-route-service command", func() { var receiver struct { Resources []resources.RouteBinding `json:"resources"` } - helpers.Curl(&receiver, "/v3/service_route_bindings?service_instance_names=%s", serviceInstanceName) + helpers.Curlf(&receiver, "/v3/service_route_bindings?service_instance_names=%s", serviceInstanceName) Expect(receiver.Resources).To(HaveLen(1)) var parametersReceiver map[string]interface{} - helpers.Curl(¶metersReceiver, `/v3/service_route_bindings/%s/parameters`, receiver.Resources[0].GUID) + helpers.Curlf(¶metersReceiver, `/v3/service_route_bindings/%s/parameters`, receiver.Resources[0].GUID) Expect(parametersReceiver).To(Equal(map[string]interface{}{"foo": "bar"})) }) }) diff --git a/integration/v7/isolated/bind_service_command_test.go b/integration/v7/isolated/bind_service_command_test.go index b766f8352c1..291da26d699 100644 --- a/integration/v7/isolated/bind_service_command_test.go +++ b/integration/v7/isolated/bind_service_command_test.go @@ -147,14 +147,14 @@ var _ = Describe("bind-service command", func() { var receiver struct { Resources []resources.ServiceCredentialBinding `json:"resources"` } - helpers.Curl(&receiver, "/v3/service_credential_bindings?service_instance_names=%s", serviceInstanceName) + helpers.Curlf(&receiver, "/v3/service_credential_bindings?service_instance_names=%s", serviceInstanceName) Expect(receiver.Resources).To(HaveLen(1)) return receiver.Resources[0] } getParameters := func(serviceInstanceName string) (receiver map[string]interface{}) { binding := getBinding(serviceInstanceName) - helpers.Curl(&receiver, "/v3/service_credential_bindings/%s/parameters", binding.GUID) + helpers.Curlf(&receiver, "/v3/service_credential_bindings/%s/parameters", binding.GUID) return } diff --git a/integration/v7/isolated/create_service_key_command_test.go b/integration/v7/isolated/create_service_key_command_test.go index ee194622651..32ee8edb2fa 100644 --- a/integration/v7/isolated/create_service_key_command_test.go +++ b/integration/v7/isolated/create_service_key_command_test.go @@ -192,11 +192,11 @@ var _ = Describe("create-service-key command", func() { var receiver struct { Resources []resources.ServiceCredentialBinding `json:"resources"` } - helpers.Curl(&receiver, "/v3/service_credential_bindings?service_instance_names=%s", serviceInstanceName) + helpers.Curlf(&receiver, "/v3/service_credential_bindings?service_instance_names=%s", serviceInstanceName) Expect(receiver.Resources).To(HaveLen(1)) var parametersReceiver map[string]interface{} - helpers.Curl(¶metersReceiver, `/v3/service_credential_bindings/%s/parameters`, receiver.Resources[0].GUID) + helpers.Curlf(¶metersReceiver, `/v3/service_credential_bindings/%s/parameters`, receiver.Resources[0].GUID) Expect(parametersReceiver).To(Equal(params)) } diff --git a/integration/v7/isolated/unbind_route_service_command_test.go b/integration/v7/isolated/unbind_route_service_command_test.go index 52c4782b8f7..7477176f39b 100644 --- a/integration/v7/isolated/unbind_route_service_command_test.go +++ b/integration/v7/isolated/unbind_route_service_command_test.go @@ -87,7 +87,7 @@ var _ = Describe("unbind-route-service command", func() { var receiver struct { Resources []resources.RouteBinding `json:"resources"` } - helpers.Curl(&receiver, "/v3/service_route_bindings?service_instance_names=%s", serviceInstanceName) + helpers.Curlf(&receiver, "/v3/service_route_bindings?service_instance_names=%s", serviceInstanceName) return len(receiver.Resources) } diff --git a/integration/v7/isolated/unbind_service_command_test.go b/integration/v7/isolated/unbind_service_command_test.go index b6646c7d3eb..2ad21289dfa 100644 --- a/integration/v7/isolated/unbind_service_command_test.go +++ b/integration/v7/isolated/unbind_service_command_test.go @@ -85,7 +85,7 @@ var _ = Describe("unbind-service command", func() { var receiver struct { Resources []resources.ServiceCredentialBinding `json:"resources"` } - helpers.Curl(&receiver, "/v3/service_credential_bindings?service_instance_names=%s", serviceInstanceName) + helpers.Curlf(&receiver, "/v3/service_credential_bindings?service_instance_names=%s", serviceInstanceName) return len(receiver.Resources) } diff --git a/integration/v7/push/droplet_flag_test.go b/integration/v7/push/droplet_flag_test.go index cf7378bc802..5eb14a49e68 100644 --- a/integration/v7/push/droplet_flag_test.go +++ b/integration/v7/push/droplet_flag_test.go @@ -93,9 +93,9 @@ var _ = Describe("--droplet flag", func() { GUID string `json:"guid"` } - currentDropletEndpoint := fmt.Sprintf("v3/apps/%s/droplets/current", originalAppGUID) + const droppletEndpointFormat = "v3/apps/%s/droplets/current" - helpers.Curl(&routeResponse, currentDropletEndpoint) + helpers.Curlf(&routeResponse, droppletEndpointFormat, originalAppGUID) preUploadDropletGUID := routeResponse.GUID session := helpers.CF(PushCommandName, originalApp, "--droplet", dropletPath, "--no-start") @@ -104,7 +104,7 @@ var _ = Describe("--droplet flag", func() { Eventually(session).Should(Say(`requested state:\s+stopped`)) Eventually(session).Should(Exit(0)) - helpers.Curl(&routeResponse, currentDropletEndpoint) + helpers.Curlf(&routeResponse, droppletEndpointFormat, originalAppGUID) postUploadDropletGUID := routeResponse.GUID Expect(preUploadDropletGUID).To(Not(Equal(postUploadDropletGUID))) diff --git a/plugin/plugin_examples/README.md b/plugin/plugin_examples/README.md index 44a088f8e18..b4cf7ddd939 100644 --- a/plugin/plugin_examples/README.md +++ b/plugin/plugin_examples/README.md @@ -14,15 +14,15 @@ Our current plugin architecture currently requires a review and possible large o # Changes in v6.14.0 - API `AccessToken()` now provides a refreshed o-auth token. -- [Examples](https://github.com/cloudfoundry/cli/tree/master/plugin/plugin_examples#test-driven-development-tdd) on how to use fake `CliConnection` and test RPC server for TDD development. +- [Examples](https://github.com/cloudfoundry/cli/tree/v8/plugin/plugin_examples#test-driven-development-tdd) on how to use fake `CliConnection` and test RPC server for TDD development. - Fix Plugin API file descriptors leakage. - Fix bug where some CLI versions does not respect `PluginMetadata.MinCliVersion`. - The field `PackageUpdatedAt` returned by `GetApp()` API is now populated. -[Complete change log ...](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/CHANGELOG.md) +[Complete change log ...](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/CHANGELOG.md) # Developing a Plugin -[Go here for documentation of the plugin API](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/DOC.md) +[Go here for documentation of the plugin API](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/DOC.md) This README discusses how to develop a cf CLI plugin. For user-focused documentation, see [Using the cf CLI](http://docs.cloudfoundry.org/cf-cli/use-cli-plugins.html). @@ -50,26 +50,26 @@ Here is an illustration of the work flow when a plugin command is being invoked. 1: CLI launches 2 processes, the rpc server and the independent plugin executable

-workflow 1 +workflow 1

2: Plugin establishes a connection to the RPC server, the connection is used to invoke core cli commands.

-workflow 1 +workflow 1

3: When a plugin invokes a cli command, it talks to the rpc server, and the rpc server interacts with cf cli to perform the command. The result is passed back to the plugin through the rpc server.

-workflow 1 +workflow 1

- Plugins that you develop for the cf CLI must conform to a predefined plugin interface that we discuss below. ## Writing a Plugin -[Go here for documentation of the plugin API](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/DOC.md) +[Go here for documentation of the plugin API](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/DOC.md) -To write a plugin for the cf CLI, implement the [predefined plugin interface](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin.go). +To write a plugin for the cf CLI, implement the [predefined plugin interface](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin.go). The interface uses a `Run(...)` method as the main entry point between the CLI and a plugin. This method receives the following arguments: @@ -82,21 +82,21 @@ Plugin names with spaces must be enclosed in quotes when installed and uninstall To initialize a plugin, call `plugin.Start(new(MyPluginStruct))` from within the `main()` method of your plugin. The `plugin.Start(...)` function requires a new reference to the struct that implements the defined interface. -This repo contains a basic plugin example [here](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/basic_plugin.go).
-To see more examples, go [here](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/). +This repo contains a basic plugin example [here](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/basic_plugin/basic_plugin.go).
+To see more examples, go [here](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/). ### Uninstalling A Plugin Uninstall of the plugin needs to be explicitly handled. When a user calls the `cf uninstall-plugin` command, CLI notifies the plugin via a call with `CLI-MESSAGE-UNINSTALL` as the first item in `[]args` from within the plugin's `Run(...)` method. ### Test Driven Development (TDD) An example which was developed using TDD is available: -- `Test RPC server`: an RPC server to be used as a back-end for the plugin. It allows the plugin to be tested as a stand alone binary without replying on CLI as a back-end. [See example](https://github.com/cloudfoundry/cli/tree/master/plugin/plugin_examples/test_rpc_server_example) +- `Test RPC server`: an RPC server to be used as a back-end for the plugin. It allows the plugin to be tested as a stand alone binary without replying on CLI as a back-end. [See example](https://github.com/cloudfoundry/cli/tree/v8/plugin/plugin_examples/test_rpc_server_example) ### Using Command Line Arguments The `Run(...)` method accepts the command line arguments and flags that you define for a plugin. - See the [command line arguments example] (https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/echo.go) included in this repo. + See the [command line arguments example] (https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/echo/echo.go) included in this repo. #### Global Flags There are several global flags that will not be passed to the plugin. These are: @@ -109,15 +109,15 @@ You can invoke CLI commands with `cliConnection.CliCommand([]args)` from within The `cliConnection.CliCommand([]args)` returns the output printed by the command and an error. The output is returned as a slice of strings. The error will be present if the call to the CLI command fails. -See the [test plugin example](https://github.com/cloudfoundry/cli/blob/master/integration/assets/test_plugin/test_plugin.go) included in this repo. +See the [test plugin example](https://github.com/cloudfoundry/cli/blob/v8/integration/assets/test_plugin/test_plugin.go) included in this repo. ### Creating Interactive Plugins -Because a plugin has access to stdin during a call to the `Run(...)` method, you can create interactive plugins. See the [interactive plugin example](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/interactive.go) included in this repo. +Because a plugin has access to stdin during a call to the `Run(...)` method, you can create interactive plugins. See the [interactive plugin example](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/interactive/interactive.go) included in this repo. ### Creating Plugins with multiple commands -A single plugin binary can have more than one command, and each command can have it's own help text defined. For an example of multi-command plugins, see the [multiple commands example](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin_examples/multiple_commands.go) +A single plugin binary can have more than one command, and each command can have it's own help text defined. For an example of multi-command plugins, see the [multiple commands example](https://github.com/cloudfoundry/cli/blob/v8/plugin/plugin_examples/multiple_commands/multiple_commands.go) ### Enforcing a minimum CLI version required for the plugin. diff --git a/plugin/plugin_examples/basic_plugin.go b/plugin/plugin_examples/basic_plugin/basic_plugin.go similarity index 100% rename from plugin/plugin_examples/basic_plugin.go rename to plugin/plugin_examples/basic_plugin/basic_plugin.go diff --git a/plugin/plugin_examples/echo.go b/plugin/plugin_examples/echo/echo.go similarity index 100% rename from plugin/plugin_examples/echo.go rename to plugin/plugin_examples/echo/echo.go diff --git a/plugin/plugin_examples/interactive.go b/plugin/plugin_examples/interactive/interactive.go similarity index 100% rename from plugin/plugin_examples/interactive.go rename to plugin/plugin_examples/interactive/interactive.go diff --git a/plugin/plugin_examples/multiple_commands.go b/plugin/plugin_examples/multiple_commands/multiple_commands.go similarity index 100% rename from plugin/plugin_examples/multiple_commands.go rename to plugin/plugin_examples/multiple_commands/multiple_commands.go diff --git a/plugin/plugin_shim_test.go b/plugin/plugin_shim_test.go index 24b49226655..04604b9570f 100644 --- a/plugin/plugin_shim_test.go +++ b/plugin/plugin_shim_test.go @@ -15,7 +15,7 @@ import ( var _ = Describe("Command", func() { var ( - validPluginPath = filepath.Join("..", "fixtures", "plugins", "test_1.exe") + validPluginPath = filepath.Join("..", "fixtures", "plugins", "test_1", "test_1.exe") ) Describe(".Start", func() { diff --git a/plugin/plugin_suite_test.go b/plugin/plugin_suite_test.go index 8076cb8955e..8c318db9fc4 100644 --- a/plugin/plugin_suite_test.go +++ b/plugin/plugin_suite_test.go @@ -11,6 +11,6 @@ import ( func TestPlugin(t *testing.T) { RegisterFailHandler(Fail) - pluginbuilder.BuildTestBinary(filepath.Join("..", "fixtures", "plugins"), "test_1") + pluginbuilder.BuildTestBinary(filepath.Join("..", "fixtures", "plugins", "test_1"), "test_1") RunSpecs(t, "Plugin Suite") } From 11c48932d6c5a06865ead67771a8cdbf3455daa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pereira?= Date: Tue, 5 Nov 2024 15:05:51 -0600 Subject: [PATCH 04/21] Add default nodes for integration tests (#3290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: João Pereira --- .github/workflows/tests-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 0a67252b7c5..ed988c0eb31 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -293,7 +293,7 @@ jobs: gitRef: ${{needs.get-sha.outputs.gitRef}} lease-id: ${{ needs.claim-env.outputs.leaseid }} lease-namespace: ${{ inputs.lease_namespace || vars.SHEPHERD_LEASE_NAMESPACE || 'tas-devex' }} - nodes: ${{ inputs.nodes }} + nodes: ${{ inputs.nodes || '16' }} secrets: inherit run-integration-tests-cf-env-with-client-creds: From 912164f928ba50c62e21c480de3b3bc607e699f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pereira?= Date: Wed, 6 Nov 2024 08:41:47 -0600 Subject: [PATCH 05/21] [v8] Provide default version based on latest tag in branch (#3284) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Provide default version based on latest tag in branch Signed-off-by: João Pereira --- .github/workflows/tests-integration-reusable.yml | 1 + .github/workflows/tests-integration.yml | 1 + Makefile | 1 + version/version.go | 8 +++++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests-integration-reusable.yml b/.github/workflows/tests-integration-reusable.yml index 4e1ee3cc356..518b866920f 100644 --- a/.github/workflows/tests-integration-reusable.yml +++ b/.github/workflows/tests-integration-reusable.yml @@ -50,6 +50,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{inputs.gitRef}} + fetch-depth: 0 - name: Checkout cf-acceptance-tests if: ${{ inputs.name == 'cats' }} diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index ed988c0eb31..20e220df18d 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -99,6 +99,7 @@ jobs: if: ${{ inputs.run_unit_tests }} with: ref: ${{needs.get-sha.outputs.gitRef}} + fetch-depth: 0 - name: Set Up Go uses: actions/setup-go@v5 if: ${{ inputs.run_unit_tests }} diff --git a/Makefile b/Makefile index fca5f3607dd..8d1dd2ffa69 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ FLAKE_ATTEMPTS ?=5 PACKAGES ?= api actor command types util version integration/helpers LC_ALL = "en_US.UTF-8" +CF_BUILD_VERSION ?= $$(git describe --tags --abbrev=0) CF_BUILD_SHA ?= $$(git rev-parse --short HEAD) CF_BUILD_DATE ?= $$(date -u +"%Y-%m-%d") LD_FLAGS_COMMON=-w -s \ diff --git a/version/version.go b/version/version.go index 47a77f878d5..4878c51b59a 100644 --- a/version/version.go +++ b/version/version.go @@ -1,6 +1,10 @@ package version -import "github.com/blang/semver/v4" +import ( + "strings" + + "github.com/blang/semver/v4" +) const DefaultVersion = "0.0.0-unknown-version" @@ -11,6 +15,8 @@ var ( ) func VersionString() string { + // Remove the "v" prefix from the binary in case it is present + binaryVersion = strings.TrimPrefix(binaryVersion, "v") versionString, err := semver.Make(binaryVersion) if err != nil { versionString = semver.MustParse(DefaultVersion) From 08454994dbab20d6bcff687d1acff763660c7b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pereira?= Date: Wed, 6 Nov 2024 16:38:04 -0600 Subject: [PATCH 06/21] [v8] Make retrieval of tasks in bulk instead of small increments (#3276) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make retrieval of tasks in bulk instead of small increments Signed-off-by: João Pereira * Address PR comments - Fix issue, where code was always doing 2 requests even when it was able to get all the tasks in the first request Signed-off-by: João Pereira * Fix lack of output Signed-off-by: João Pereira * Remove extra tasks from first request Signed-off-by: João Pereira * Change approach by providing the query parameters always to the request Signed-off-by: João Pereira --------- Signed-off-by: João Pereira --- .../ccv3/included_resources.go | 11 ++ api/cloudcontroller/ccv3/paginate.go | 9 +- api/cloudcontroller/ccv3/task.go | 10 ++ api/cloudcontroller/ccv3/task_test.go | 164 +++++++++++++++++- 4 files changed, 183 insertions(+), 11 deletions(-) diff --git a/api/cloudcontroller/ccv3/included_resources.go b/api/cloudcontroller/ccv3/included_resources.go index 0044707663a..24f3b5a0c01 100644 --- a/api/cloudcontroller/ccv3/included_resources.go +++ b/api/cloudcontroller/ccv3/included_resources.go @@ -12,3 +12,14 @@ type IncludedResources struct { ServicePlans []resources.ServicePlan `json:"service_plans,omitempty"` Apps []resources.Application `json:"apps,omitempty"` } + +func (i *IncludedResources) Merge(resources IncludedResources) { + i.Apps = append(i.Apps, resources.Apps...) + i.Users = append(i.Users, resources.Users...) + i.Organizations = append(i.Organizations, resources.Organizations...) + i.Spaces = append(i.Spaces, resources.Spaces...) + i.ServiceBrokers = append(i.ServiceBrokers, resources.ServiceBrokers...) + i.ServiceInstances = append(i.ServiceInstances, resources.ServiceInstances...) + i.ServiceOfferings = append(i.ServiceOfferings, resources.ServiceOfferings...) + i.ServicePlans = append(i.ServicePlans, resources.ServicePlans...) +} diff --git a/api/cloudcontroller/ccv3/paginate.go b/api/cloudcontroller/ccv3/paginate.go index bf87cce32ec..a31fe0ec5b3 100644 --- a/api/cloudcontroller/ccv3/paginate.go +++ b/api/cloudcontroller/ccv3/paginate.go @@ -17,14 +17,7 @@ func (requester RealRequester) paginate(request *cloudcontroller.Request, obj in return IncludedResources{}, fullWarningsList, err } - includes.Apps = append(includes.Apps, wrapper.IncludedResources.Apps...) - includes.Users = append(includes.Users, wrapper.IncludedResources.Users...) - includes.Organizations = append(includes.Organizations, wrapper.IncludedResources.Organizations...) - includes.Spaces = append(includes.Spaces, wrapper.IncludedResources.Spaces...) - includes.ServiceBrokers = append(includes.ServiceBrokers, wrapper.IncludedResources.ServiceBrokers...) - includes.ServiceInstances = append(includes.ServiceInstances, wrapper.IncludedResources.ServiceInstances...) - includes.ServiceOfferings = append(includes.ServiceOfferings, wrapper.IncludedResources.ServiceOfferings...) - includes.ServicePlans = append(includes.ServicePlans, wrapper.IncludedResources.ServicePlans...) + includes.Merge(wrapper.IncludedResources) if specificPage || wrapper.NextPage() == "" { break diff --git a/api/cloudcontroller/ccv3/task.go b/api/cloudcontroller/ccv3/task.go index 359ee9277a4..91c99814eaa 100644 --- a/api/cloudcontroller/ccv3/task.go +++ b/api/cloudcontroller/ccv3/task.go @@ -25,6 +25,16 @@ func (client *Client) CreateApplicationTask(appGUID string, task resources.Task) func (client *Client) GetApplicationTasks(appGUID string, query ...Query) ([]resources.Task, Warnings, error) { var tasks []resources.Task + foundPerPageQuery := false + for _, keyVal := range query { + if keyVal.Key == PerPage { + foundPerPageQuery = true + } + } + if !foundPerPageQuery { + query = append(query, Query{Key: PerPage, Values: []string{MaxPerPage}}) + } + _, warnings, err := client.MakeListRequest(RequestParams{ RequestName: internal.GetApplicationTasksRequest, URIParams: internal.Params{"app_guid": appGUID}, diff --git a/api/cloudcontroller/ccv3/task_test.go b/api/cloudcontroller/ccv3/task_test.go index c45c4d4b7a3..bfa411ddf28 100644 --- a/api/cloudcontroller/ccv3/task_test.go +++ b/api/cloudcontroller/ccv3/task_test.go @@ -190,9 +190,18 @@ var _ = Describe("Task", func() { warnings Warnings executeErr error ) + BeforeEach(func() { + // This is required because ginkgo does not instantiate variable per test context so the tests pollute the + // variables for the next tests. + submitQuery = Query{} + }) JustBeforeEach(func() { - tasks, warnings, executeErr = client.GetApplicationTasks("some-app-guid", submitQuery) + if submitQuery.Key == "" { + tasks, warnings, executeErr = client.GetApplicationTasks("some-app-guid") + } else { + tasks, warnings, executeErr = client.GetApplicationTasks("some-app-guid", submitQuery) + } }) When("the application exists", func() { @@ -201,7 +210,8 @@ var _ = Describe("Task", func() { "pagination": { "next": { "href": "%s/v3/apps/some-app-guid/tasks?per_page=2&page=2" - } + }, + "total_results": 3 }, "resources": [ { @@ -245,7 +255,7 @@ var _ = Describe("Task", func() { ) server.AppendHandlers( CombineHandlers( - VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "per_page=2&page=2"), + VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "page=2&per_page=2"), RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"warning-2"}}), ), ) @@ -353,6 +363,154 @@ var _ = Describe("Task", func() { Expect(warnings).To(ConsistOf("warning")) }) }) + + When("the application has 10000 tasks", func() { + BeforeEach(func() { + response2 := fmt.Sprintf(`{ + "pagination": { + "next": { + "href": "%s/v3/apps/some-app-guid/tasks?per_page=5000&page=2" + }, + "total_results": 10000 + }, + "resources": [ + { + "guid": "task-1-guid", + "sequence_id": 1, + "name": "task-1", + "command": "some-command", + "state": "SUCCEEDED", + "created_at": "2016-11-07T05:59:01Z" + }, + { + "guid": "task-2-guid", + "sequence_id": 2, + "name": "task-2", + "command": "some-command", + "state": "FAILED", + "created_at": "2016-11-07T06:59:01Z" + } + ] + }`, server.URL()) + response3 := fmt.Sprintf(`{ + "pagination": { + "total_results": 10000 + }, + "resources": [ + { + "guid": "task-1-guid", + "sequence_id": 1, + "name": "task-1", + "command": "some-command", + "state": "SUCCEEDED", + "created_at": "2016-11-07T05:59:01Z" + }, + { + "guid": "task-2-guid", + "sequence_id": 2, + "name": "task-2", + "command": "some-command", + "state": "FAILED", + "created_at": "2016-11-07T06:59:01Z" + } + ] + }`) + + server.AppendHandlers( + CombineHandlers( + VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "per_page=5000"), + RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"warning-2"}}), + ), + ) + server.AppendHandlers( + CombineHandlers( + VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "page=2&per_page=5000"), + RespondWith(http.StatusOK, response3, http.Header{"X-Cf-Warnings": {"warning-2"}}), + ), + ) + }) + + It("calls CAPI 2 times", func() { + Expect(executeErr).ToNot(HaveOccurred()) + }) + }) + + When("the application has 4999 tasks", func() { + BeforeEach(func() { + response2 := fmt.Sprintf(`{ + "pagination": { + "total_results": 4999 + }, + "resources": [ + { + "guid": "task-1-guid", + "sequence_id": 1, + "name": "task-1", + "command": "some-command", + "state": "SUCCEEDED", + "created_at": "2016-11-07T05:59:01Z" + }, + { + "guid": "task-2-guid", + "sequence_id": 2, + "name": "task-2", + "command": "some-command", + "state": "FAILED", + "created_at": "2016-11-07T06:59:01Z" + } + ] + }`) + server.AppendHandlers( + CombineHandlers( + VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "per_page=5000"), + RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"warning-2"}}), + ), + ) + }) + + It("calls CAPI 2 times", func() { + Expect(executeErr).ToNot(HaveOccurred()) + }) + }) + + When("the application has 2 tasks", func() { + BeforeEach(func() { + response1 := fmt.Sprintf(`{ + "pagination": { + "total_results": 2 + }, + "resources": [ + { + "guid": "task-1-guid", + "sequence_id": 1, + "name": "task-1", + "command": "some-command", + "state": "SUCCEEDED", + "created_at": "2016-11-07T05:59:01Z" + }, + { + "guid": "task-2-guid", + "sequence_id": 2, + "name": "task-2", + "command": "some-command", + "state": "FAILED", + "created_at": "2016-11-07T06:59:01Z" + } + ] + }`) + + server.AppendHandlers( + CombineHandlers( + VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks"), + RespondWith(http.StatusAccepted, response1, http.Header{"X-Cf-Warnings": {"warning"}}), + ), + ) + }) + + It("calls CAPI 1 time", func() { + Expect(executeErr).ToNot(HaveOccurred()) + }) + }) }) Describe("UpdateTaskCancel", func() { From 0eb2dee7ee7abe0dcc0b402d31b60bdeac15403d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:30:19 -0800 Subject: [PATCH 07/21] [v8](go): Bump the dependencies group with 7 updates (#3278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the dependencies group with 7 updates: | Package | From | To | | --- | --- | --- | | [code.cloudfoundry.org/bytefmt](https://github.com/cloudfoundry/bytefmt) | `0.14.0` | `0.16.0` | | [code.cloudfoundry.org/clock](https://github.com/cloudfoundry/clock) | `1.17.0` | `1.19.0` | | [code.cloudfoundry.org/lager/v3](https://github.com/cloudfoundry/lager) | `3.11.0` | `3.13.0` | | [code.cloudfoundry.org/tlsconfig](https://github.com/cloudfoundry/tlsconfig) | `0.7.0` | `0.8.0` | | [github.com/creack/pty](https://github.com/creack/pty) | `1.1.23` | `1.1.24` | | [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) | `2.20.2` | `2.21.0` | | [github.com/onsi/gomega](https://github.com/onsi/gomega) | `1.34.2` | `1.35.1` | Updates `code.cloudfoundry.org/bytefmt` from 0.14.0 to 0.16.0 - [Release notes](https://github.com/cloudfoundry/bytefmt/releases) - [Commits](https://github.com/cloudfoundry/bytefmt/compare/v0.14.0...v0.16.0) Updates `code.cloudfoundry.org/clock` from 1.17.0 to 1.19.0 - [Release notes](https://github.com/cloudfoundry/clock/releases) - [Commits](https://github.com/cloudfoundry/clock/compare/v1.17.0...v1.19.0) Updates `code.cloudfoundry.org/lager/v3` from 3.11.0 to 3.13.0 - [Release notes](https://github.com/cloudfoundry/lager/releases) - [Commits](https://github.com/cloudfoundry/lager/compare/v3.11.0...v3.13.0) Updates `code.cloudfoundry.org/tlsconfig` from 0.7.0 to 0.8.0 - [Release notes](https://github.com/cloudfoundry/tlsconfig/releases) - [Commits](https://github.com/cloudfoundry/tlsconfig/compare/v0.7.0...v0.8.0) Updates `github.com/creack/pty` from 1.1.23 to 1.1.24 - [Release notes](https://github.com/creack/pty/releases) - [Commits](https://github.com/creack/pty/compare/v1.1.23...v1.1.24) Updates `github.com/onsi/ginkgo/v2` from 2.20.2 to 2.21.0 - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.20.2...v2.21.0) Updates `github.com/onsi/gomega` from 1.34.2 to 1.35.1 - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.34.2...v1.35.1) --- updated-dependencies: - dependency-name: code.cloudfoundry.org/bytefmt dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/clock dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/lager/v3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/tlsconfig dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: github.com/creack/pty dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: João Pereira --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 4efb3c2e34a..f20cc28d9db 100644 --- a/go.mod +++ b/go.mod @@ -3,23 +3,23 @@ module code.cloudfoundry.org/cli go 1.23.1 require ( - code.cloudfoundry.org/bytefmt v0.14.0 + code.cloudfoundry.org/bytefmt v0.16.0 code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 - code.cloudfoundry.org/clock v1.17.0 + code.cloudfoundry.org/clock v1.19.0 code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 code.cloudfoundry.org/go-log-cache/v2 v2.0.7 code.cloudfoundry.org/go-loggregator/v9 v9.2.1 code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f code.cloudfoundry.org/jsonry v1.1.4 - code.cloudfoundry.org/lager/v3 v3.11.0 - code.cloudfoundry.org/tlsconfig v0.7.0 + code.cloudfoundry.org/lager/v3 v3.13.0 + code.cloudfoundry.org/tlsconfig v0.8.0 code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 github.com/blang/semver/v4 v4.0.0 github.com/cloudfoundry/bosh-cli v6.4.1+incompatible - github.com/creack/pty v1.1.23 + github.com/creack/pty v1.1.24 github.com/cyphar/filepath-securejoin v0.3.4 github.com/distribution/reference v0.6.0 github.com/fatih/color v1.18.0 @@ -31,8 +31,8 @@ require ( github.com/maxbrunsfeld/counterfeiter/v6 v6.10.0 github.com/moby/term v0.5.0 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d - github.com/onsi/ginkgo/v2 v2.20.2 - github.com/onsi/gomega v1.34.2 + github.com/onsi/ginkgo/v2 v2.21.0 + github.com/onsi/gomega v1.35.1 github.com/pkg/errors v0.9.1 github.com/sabhiram/go-gitignore v0.0.0-20171017070213-362f9845770f github.com/sajari/fuzzy v1.0.0 @@ -65,7 +65,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20241021161924-4cf4322d492d // indirect + github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -88,7 +88,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 90b291510ce..96a4a170b10 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ -code.cloudfoundry.org/bytefmt v0.14.0 h1:F109/rZI5mLOP2+BLj9TOzz3M3qVQ/F1IrI1fsRzakU= -code.cloudfoundry.org/bytefmt v0.14.0/go.mod h1:KkTqS6HXZkTOfw2Wvm0+R82P+p13nVS7bQddej57WJI= +code.cloudfoundry.org/bytefmt v0.16.0 h1:MYcmMBZDIL6H3jVD1lu7Fn/gSI5I45wxat4cq3DwT9o= +code.cloudfoundry.org/bytefmt v0.16.0/go.mod h1:1qOzTFyq3A3MhUgMRlDIcZNeoEN0nkXyE+TWWgwogAo= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 h1:Yc9r1p21kEpni9WlG4mwOZw87TB2QlyS9sAEebZ3+ak= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6/go.mod h1:u5FovqC5GGAEbFPz+IdjycDA+gIjhUwqxnu0vbHwVeM= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 h1:jaHWw9opYjKPrDT19uydBBWSxl+g5F4Hv030fqMsalo= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85/go.mod h1:R1EiyOAr7lW0l/YkZNqItUNZ01Q/dYUfbTn4X4Z+82M= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 h1:O+j8afQWaDuxzKGcculsjgHGK+biBTn6iMjgFpBf54c= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4/go.mod h1:dVTgo9kQbYns/QM4A1C2GtxqUnFSvJTk2Qhw+M0/uzk= -code.cloudfoundry.org/clock v1.17.0 h1:0Zo1EIJkYSQdo6vv97rt5gzSXymjyXnjOzashoKEO6w= -code.cloudfoundry.org/clock v1.17.0/go.mod h1:5SbAgLf/ZTQY11g3jB68e94/DKtZHr9DJbD8h6xUdTg= +code.cloudfoundry.org/clock v1.19.0 h1:63BijjbNMSzEXk0UwpJBbiZoE2HpVoVA1nsRaBrZ684= +code.cloudfoundry.org/clock v1.19.0/go.mod h1:rMhV7iqb/VE9wutZcqKQ10S3q/VJ/tBvGvlOGlTH7Vg= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 h1:Bns1y0jSlcvfP0u8ael+TUlnyNHsNX808zuo58bf5so= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82/go.mod h1:L2/glHnSK+wKnsG8oZZqdV2sgYY9NDo/I1aDJGhcWaM= code.cloudfoundry.org/go-log-cache/v2 v2.0.7 h1:yR/JjQ/RscO1n4xVAT9HDYcpx5ET/3Cq2/RhpJml6ZU= @@ -21,10 +21,10 @@ code.cloudfoundry.org/inigo v0.0.0-20230612153013-b300679e6ed6/go.mod h1:1ZB1JCh code.cloudfoundry.org/jsonry v1.1.4 h1:P9N7IlH1/4aRCLcXLgLFj1hkcBmV7muijJzY+K6U4hE= code.cloudfoundry.org/jsonry v1.1.4/go.mod h1:6aKilShQP7w/Ez76h1El2/n9y2OkHuU56nKSBB9Gp0A= code.cloudfoundry.org/lager v1.1.1-0.20191008172124-a9afc05ee5be/go.mod h1:O2sS7gKP3HM2iemG+EnwvyNQK7pTSC6Foi4QiMp9sSk= -code.cloudfoundry.org/lager/v3 v3.11.0 h1:YjRSl1USPIz1FFZPVvwFYgXUUodSIWDdXaLVvME3jZg= -code.cloudfoundry.org/lager/v3 v3.11.0/go.mod h1:8Ot/5fRETEzdf9U3N1kCWp00oZteNwew5Cl2Ck3t2ho= -code.cloudfoundry.org/tlsconfig v0.7.0 h1:/gD+YzQtjjmUjW0W/NamX9zX6cX679jV1QDEH34kfAc= -code.cloudfoundry.org/tlsconfig v0.7.0/go.mod h1:S6L3WxtIy4a4wPnmtqUQXiIYlrIk7tUIXj5z+5QYqGY= +code.cloudfoundry.org/lager/v3 v3.13.0 h1:6FXwixz8K3+AKGI82tvJ1Zhl/So+tTJdkZ+EWgWVwB8= +code.cloudfoundry.org/lager/v3 v3.13.0/go.mod h1:s9leys6zsUSrlKzEPqa0/8tMdvqtERzxQYDYp+zbMng= +code.cloudfoundry.org/tlsconfig v0.8.0 h1:2kg6Y8ix58T+84iDu1yAFEx6wsHfkg5Mah4twdtbeIs= +code.cloudfoundry.org/tlsconfig v0.8.0/go.mod h1:S6L3WxtIy4a4wPnmtqUQXiIYlrIk7tUIXj5z+5QYqGY= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d h1:M+zXqtXJqcsmpL76aU0tdl1ho23eYa4axYoM4gD62UA= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d/go.mod h1:YUJiVOr5xl0N/RjMxM1tHmgSpBbi5UM+KoVR5AoejO0= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -56,8 +56,8 @@ github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2 github.com/cppforlife/go-patch v0.1.0 h1:I0fT+gFTSW4xWwvaTaUUVjr9xxjNXJ4naGc01BeQjwY= github.com/cppforlife/go-patch v0.1.0/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= -github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -124,8 +124,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20241021161924-4cf4322d492d h1:dcUSYLuKITgwgLZJZpB+CKecsC8mXHhErghMX9ohbf4= -github.com/google/pprof v0.0.0-20241021161924-4cf4322d492d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -197,8 +197,8 @@ github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= -github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v0.0.0-20171105031654-1eecca0ba8e6/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -207,8 +207,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= @@ -370,8 +370,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 45c5c89443237feaff0c8de99e25937009bee049 Mon Sep 17 00:00:00 2001 From: Shwetha Gururaj Date: Mon, 11 Nov 2024 10:48:08 -0500 Subject: [PATCH 08/21] Make cups command idempotent (#3289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Pereira --- .../v7/create_user_provided_service_command.go | 12 +++++++++++- .../create_user_provided_service_command_test.go | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/command/v7/create_user_provided_service_command.go b/command/v7/create_user_provided_service_command.go index fbe7a412bda..7b6b5fc27c7 100644 --- a/command/v7/create_user_provided_service_command.go +++ b/command/v7/create_user_provided_service_command.go @@ -1,6 +1,7 @@ package v7 import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/command" "code.cloudfoundry.org/cli/command/flag" "code.cloudfoundry.org/cli/resources" @@ -43,7 +44,16 @@ func (cmd CreateUserProvidedServiceCommand) Execute(args []string) error { warnings, err := cmd.Actor.CreateUserProvidedServiceInstance(serviceInstance) cmd.UI.DisplayWarnings(warnings) - if err != nil { + switch err.(type) { + case nil: + case ccerror.ServiceInstanceNameTakenError: + cmd.UI.DisplayTextWithFlavor("Service instance {{.ServiceInstanceName}} already exists", + map[string]interface{}{ + "ServiceInstanceName": serviceInstance.Name, + }) + cmd.UI.DisplayOK() + return nil + default: return err } diff --git a/command/v7/create_user_provided_service_command_test.go b/command/v7/create_user_provided_service_command_test.go index bccc37e67fd..c63c24c86d6 100644 --- a/command/v7/create_user_provided_service_command_test.go +++ b/command/v7/create_user_provided_service_command_test.go @@ -3,6 +3,7 @@ package v7_test import ( "errors" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/types" "code.cloudfoundry.org/cli/actor/v7action" @@ -215,5 +216,20 @@ var _ = Describe("create-user-provided-service Command", func() { )) }) }) + + When("the service instance name is taken", func() { + BeforeEach(func() { + fakeActor.CreateUserProvidedServiceInstanceReturns( + nil, + ccerror.ServiceInstanceNameTakenError{}, + ) + }) + + It("succeeds, displaying warnings, 'OK' and an informative message", func() { + Expect(executeErr).NotTo(HaveOccurred()) + Expect(testUI.Out).To(Say("Service instance %s already exists", fakeServiceInstanceName)) + Expect(testUI.Out).To(Say("OK")) + }) + }) }) }) From 2c63b87f55893c29a17ac2595316b3dc4378282d Mon Sep 17 00:00:00 2001 From: AL Berez Date: Mon, 11 Nov 2024 08:46:31 -0800 Subject: [PATCH 09/21] Optimize units workflow [v8] (#3291) * Optimize units workflow * Run units of windows * Add back windows-2019 * Make naming more expressive * Move to run-name --- .github/workflows/tests-unit.yml | 61 +++++++++++--------------------- 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/.github/workflows/tests-unit.yml b/.github/workflows/tests-unit.yml index 94ca66df7fa..8a53e4f4cad 100644 --- a/.github/workflows/tests-unit.yml +++ b/.github/workflows/tests-unit.yml @@ -1,4 +1,11 @@ -name: "Tests" +name: Unit Tests + +run-name: >- + Unit Tests: + ${{ github.event_name == 'pull_request' + && format('PR #{0} - {1}', github.event.pull_request.number, github.event.pull_request.title) + || format('{0} to {1}', github.event_name, github.ref_name) + }} on: workflow_dispatch: @@ -21,13 +28,9 @@ on: permissions: contents: read -defaults: - run: - shell: bash - jobs: - units: - name: Units + unit-tests: + name: Unit Tests (${{ matrix.os }}) strategy: fail-fast: false matrix: @@ -36,51 +39,29 @@ jobs: - ubuntu-20.04 - macos-latest - macos-13 - runs-on: ${{ matrix.os }} - steps: - - - name: Checkout - uses: actions/checkout@v4 - - - name: Set Up Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - check-latest: true - - - name: Run Units - run: make units - - units-windows: - name: Units Windows - strategy: - fail-fast: false - matrix: - os: - windows-latest - windows-2019 runs-on: ${{ matrix.os }} defaults: run: - shell: pwsh - steps: + shell: ${{ matrix.os == 'windows-latest' && 'pwsh' || 'bash' }} - - name: Checkout + steps: + - name: Checkout Repository uses: actions/checkout@v4 - - name: Set Up Go + - name: Setup Go Environment uses: actions/setup-go@v5 with: go-version-file: go.mod check-latest: true + cache: true - - name: Get build-time dependencies - run: | - choco install --no-progress --limit-output -y make + - name: Install Windows Build Dependencies + if: matrix.os == 'windows-latest' + run: choco install --no-progress --limit-output -y make + + - name: Execute Unit Tests + run: make units - - name: Run Windows Units - run: | - Get-Command make - Get-Item Makefile - make units # vim: set sw=2 ts=2 sts=2 et tw=78 foldlevel=2 fdm=indent nospell: From 6cd0d9b3788eb741e8d0bad2d51dcc5c1a4a4b99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:38:30 -0800 Subject: [PATCH 10/21] [v8](go): Bump the dependencies group with 7 updates (#3293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the dependencies group with 7 updates: | Package | From | To | | --- | --- | --- | | [code.cloudfoundry.org/bytefmt](https://github.com/cloudfoundry/bytefmt) | `0.16.0` | `0.17.0` | | [code.cloudfoundry.org/clock](https://github.com/cloudfoundry/clock) | `1.19.0` | `1.20.0` | | [code.cloudfoundry.org/lager/v3](https://github.com/cloudfoundry/lager) | `3.13.0` | `3.14.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.28.0` | `0.29.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.30.0` | `0.31.0` | | [golang.org/x/term](https://github.com/golang/term) | `0.25.0` | `0.26.0` | | [golang.org/x/text](https://github.com/golang/text) | `0.19.0` | `0.20.0` | Updates `code.cloudfoundry.org/bytefmt` from 0.16.0 to 0.17.0 - [Release notes](https://github.com/cloudfoundry/bytefmt/releases) - [Commits](https://github.com/cloudfoundry/bytefmt/compare/v0.16.0...v0.17.0) Updates `code.cloudfoundry.org/clock` from 1.19.0 to 1.20.0 - [Release notes](https://github.com/cloudfoundry/clock/releases) - [Commits](https://github.com/cloudfoundry/clock/compare/v1.19.0...v1.20.0) Updates `code.cloudfoundry.org/lager/v3` from 3.13.0 to 3.14.0 - [Release notes](https://github.com/cloudfoundry/lager/releases) - [Commits](https://github.com/cloudfoundry/lager/compare/v3.13.0...v3.14.0) Updates `golang.org/x/crypto` from 0.28.0 to 0.29.0 - [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.29.0) Updates `golang.org/x/net` from 0.30.0 to 0.31.0 - [Commits](https://github.com/golang/net/compare/v0.30.0...v0.31.0) Updates `golang.org/x/term` from 0.25.0 to 0.26.0 - [Commits](https://github.com/golang/term/compare/v0.25.0...v0.26.0) Updates `golang.org/x/text` from 0.19.0 to 0.20.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.19.0...v0.20.0) --- updated-dependencies: - dependency-name: code.cloudfoundry.org/bytefmt dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/clock dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/lager/v3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: João Pereira --- go.mod | 20 ++++++++++---------- go.sum | 40 ++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index f20cc28d9db..877798a71c9 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,17 @@ module code.cloudfoundry.org/cli go 1.23.1 require ( - code.cloudfoundry.org/bytefmt v0.16.0 + code.cloudfoundry.org/bytefmt v0.17.0 code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 - code.cloudfoundry.org/clock v1.19.0 + code.cloudfoundry.org/clock v1.20.0 code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 code.cloudfoundry.org/go-log-cache/v2 v2.0.7 code.cloudfoundry.org/go-loggregator/v9 v9.2.1 code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f code.cloudfoundry.org/jsonry v1.1.4 - code.cloudfoundry.org/lager/v3 v3.13.0 + code.cloudfoundry.org/lager/v3 v3.14.0 code.cloudfoundry.org/tlsconfig v0.8.0 code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 @@ -39,10 +39,10 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/tedsuo/rata v1.0.1-0.20170830210128-07d200713958 github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec - golang.org/x/crypto v0.28.0 - golang.org/x/net v0.30.0 - golang.org/x/term v0.25.0 - golang.org/x/text v0.19.0 + golang.org/x/crypto v0.29.0 + golang.org/x/net v0.31.0 + golang.org/x/term v0.26.0 + golang.org/x/text v0.20.0 gopkg.in/cheggaaa/pb.v1 v1.0.28 gopkg.in/yaml.v2 v2.4.0 k8s.io/apimachinery v0.31.2 @@ -65,7 +65,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect + github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -80,8 +80,8 @@ require ( github.com/x448/float16 v0.8.4 // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.26.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect diff --git a/go.sum b/go.sum index 96a4a170b10..283a76c5487 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ -code.cloudfoundry.org/bytefmt v0.16.0 h1:MYcmMBZDIL6H3jVD1lu7Fn/gSI5I45wxat4cq3DwT9o= -code.cloudfoundry.org/bytefmt v0.16.0/go.mod h1:1qOzTFyq3A3MhUgMRlDIcZNeoEN0nkXyE+TWWgwogAo= +code.cloudfoundry.org/bytefmt v0.17.0 h1:p8lUUWcqRw1gzZp0/McEtoMytE/5f8rPo2AkE9g8Pt0= +code.cloudfoundry.org/bytefmt v0.17.0/go.mod h1:Gep8GOASWFixDTjr+1C8lEqphdvS0djnDGXrlUkDVu8= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 h1:Yc9r1p21kEpni9WlG4mwOZw87TB2QlyS9sAEebZ3+ak= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6/go.mod h1:u5FovqC5GGAEbFPz+IdjycDA+gIjhUwqxnu0vbHwVeM= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 h1:jaHWw9opYjKPrDT19uydBBWSxl+g5F4Hv030fqMsalo= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85/go.mod h1:R1EiyOAr7lW0l/YkZNqItUNZ01Q/dYUfbTn4X4Z+82M= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 h1:O+j8afQWaDuxzKGcculsjgHGK+biBTn6iMjgFpBf54c= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4/go.mod h1:dVTgo9kQbYns/QM4A1C2GtxqUnFSvJTk2Qhw+M0/uzk= -code.cloudfoundry.org/clock v1.19.0 h1:63BijjbNMSzEXk0UwpJBbiZoE2HpVoVA1nsRaBrZ684= -code.cloudfoundry.org/clock v1.19.0/go.mod h1:rMhV7iqb/VE9wutZcqKQ10S3q/VJ/tBvGvlOGlTH7Vg= +code.cloudfoundry.org/clock v1.20.0 h1:evna9D0iZm2LGEOTH1qooDdGcsTx4wfACdCArWpBpbU= +code.cloudfoundry.org/clock v1.20.0/go.mod h1:lbTmT6tMYRsX878c49dSgbn0+jO1W2iYPOcOwYyV0Yk= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 h1:Bns1y0jSlcvfP0u8ael+TUlnyNHsNX808zuo58bf5so= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82/go.mod h1:L2/glHnSK+wKnsG8oZZqdV2sgYY9NDo/I1aDJGhcWaM= code.cloudfoundry.org/go-log-cache/v2 v2.0.7 h1:yR/JjQ/RscO1n4xVAT9HDYcpx5ET/3Cq2/RhpJml6ZU= @@ -21,8 +21,8 @@ code.cloudfoundry.org/inigo v0.0.0-20230612153013-b300679e6ed6/go.mod h1:1ZB1JCh code.cloudfoundry.org/jsonry v1.1.4 h1:P9N7IlH1/4aRCLcXLgLFj1hkcBmV7muijJzY+K6U4hE= code.cloudfoundry.org/jsonry v1.1.4/go.mod h1:6aKilShQP7w/Ez76h1El2/n9y2OkHuU56nKSBB9Gp0A= code.cloudfoundry.org/lager v1.1.1-0.20191008172124-a9afc05ee5be/go.mod h1:O2sS7gKP3HM2iemG+EnwvyNQK7pTSC6Foi4QiMp9sSk= -code.cloudfoundry.org/lager/v3 v3.13.0 h1:6FXwixz8K3+AKGI82tvJ1Zhl/So+tTJdkZ+EWgWVwB8= -code.cloudfoundry.org/lager/v3 v3.13.0/go.mod h1:s9leys6zsUSrlKzEPqa0/8tMdvqtERzxQYDYp+zbMng= +code.cloudfoundry.org/lager/v3 v3.14.0 h1:W6W1VhS4df8TvXCVo0lj5ve/hjF6YarmU0hsjA/phg4= +code.cloudfoundry.org/lager/v3 v3.14.0/go.mod h1:beQQaqGk0JSc5Nl/CZFGPCY05lm/wIRa+RoJh7Hz7jI= code.cloudfoundry.org/tlsconfig v0.8.0 h1:2kg6Y8ix58T+84iDu1yAFEx6wsHfkg5Mah4twdtbeIs= code.cloudfoundry.org/tlsconfig v0.8.0/go.mod h1:S6L3WxtIy4a4wPnmtqUQXiIYlrIk7tUIXj5z+5QYqGY= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d h1:M+zXqtXJqcsmpL76aU0tdl1ho23eYa4axYoM4gD62UA= @@ -124,8 +124,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs= +github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -264,8 +264,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -288,8 +288,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -297,8 +297,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180419222023-a2a45943ae67/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -323,19 +323,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 860c8d175a7ec0389e0d548b2f7bf4b7241ccf0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:23:16 -0800 Subject: [PATCH 11/21] [v8](gha): Bump anchore/scan-action in the dependencies group (#3253) Bumps the dependencies group with 1 update: [anchore/scan-action](https://github.com/anchore/scan-action). Updates `anchore/scan-action` from 4 to 5 - [Release notes](https://github.com/anchore/scan-action/releases) - [Changelog](https://github.com/anchore/scan-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/anchore/scan-action/compare/v4...v5) --- updated-dependencies: - dependency-name: anchore/scan-action dependency-type: direct:production update-type: version-update:semver-major dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-cves.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-cves.yml b/.github/workflows/check-cves.yml index 657ca5d3ac3..947b9d56a5b 100644 --- a/.github/workflows/check-cves.yml +++ b/.github/workflows/check-cves.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v4 - name: Scan current project - uses: anchore/scan-action@v4 + uses: anchore/scan-action@v5 with: path: "." add-cpes-if-none: true From 39e9cd56771c3c1614ac57c7ed5fe565971e4124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pereira?= Date: Fri, 15 Nov 2024 17:39:11 -0600 Subject: [PATCH 12/21] Add new release valiation (#3300) --- .github/workflows/release-update-repos.yml | 5 +- .github/workflows/test-latest-releases.yml | 146 +++++++++++++++++++++ 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test-latest-releases.yml diff --git a/.github/workflows/release-update-repos.yml b/.github/workflows/release-update-repos.yml index 89cf90a9bfb..ad9967320c0 100644 --- a/.github/workflows/release-update-repos.yml +++ b/.github/workflows/release-update-repos.yml @@ -305,7 +305,10 @@ jobs: test-deb: name: Test Debian Repository - runs-on: ubuntu-20.04 + strategy: + matrix: + os: [ubuntu-22.04, ubuntu-latest] + runs-on: ${{ matrix.os }} needs: - setup - update-deb diff --git a/.github/workflows/test-latest-releases.yml b/.github/workflows/test-latest-releases.yml new file mode 100644 index 00000000000..b8639ba2aa5 --- /dev/null +++ b/.github/workflows/test-latest-releases.yml @@ -0,0 +1,146 @@ +name: "Check: Check release on package managers" +run-name: "Check: Check release on package managers [${{ github.ref_name }}]" + +on: + workflow_dispatch: + inputs: + major-version: + description: Major version to retrieve + required: true + type: choice + options: + - '8' + - '7' + version: + description: Version of CLI to check if it is present + type: string + required: true + claw-url: + description: Location of CLAW + type: string + required: true + default: https://packages.cloudfoundry.org + +defaults: + run: + shell: bash + +jobs: + test-homebrew: + name: Test Homebrew Repository + runs-on: macos-latest + env: + CLAW_URL: ${{ inputs.claw-url }} + VERSION_BUILD: ${{ inputs.version }} + VERSION_MAJOR: ${{ inputs.major-version }} + steps: + + - name: Install CF CLI via Homebrew + run: | + set -evx + + brew install cloudfoundry/tap/cf-cli@${VERSION_MAJOR} + installed_cf_version=$(cf${VERSION_MAJOR} version) + + cf_location=$(which cf) + + echo $cf_location + echo $installed_cf_version + echo ${VERSION_BUILD} + + codesign --verify $cf_location || echo --- + + cf -v | grep "${VERSION_BUILD}" + + test-deb: + name: Test Debian Repository + strategy: + matrix: + os: [ubuntu-22.04, ubuntu-latest] + runs-on: ${{ matrix.os }} + env: + CLAW_URL: ${{ inputs.claw-url }} + VERSION_BUILD: ${{ inputs.version }} + VERSION_MAJOR: ${{ inputs.major-version }} + steps: + + - name: Install CF CLI via apt + run: | + set -o pipefail -e + + sudo apt update + sudo apt install -y wget gnupg + + wget -q -O - ${CLAW_URL}/debian/cli.cloudfoundry.org.key | sudo apt-key add - + echo "deb ${CLAW_URL}/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list + + sudo apt update + sudo apt install -y cf${VERSION_MAJOR}-cli + + which cf + + set -x + + cf -v + cf${VERSION_MAJOR} -v + + cf -v | grep "${VERSION_BUILD}" + + + test-rpm-repo: + name: Test RPM Repository + runs-on: ubuntu-latest + container: + image: fedora + env: + CLAW_URL: ${{ inputs.claw-url }} + VERSION_BUILD: ${{ inputs.version }} + VERSION_MAJOR: ${{ inputs.major-version }} + steps: + + - name: Configure Custom CF Repository + run: | + curl -sL -o /etc/yum.repos.d/cloudfoundry-cli.repo \ + ${CLAW_URL}/fedora/cloudfoundry-cli.repo + + - name: Install cf cli package + run: dnf install -y cf${VERSION_MAJOR}-cli + + - name: Print CF CLI Versions + run: | + cf -v + cf${VERSION_MAJOR} -v + + - name: Test Version Match + run: cf -v | grep -q "${VERSION_BUILD}" + + test-windows: + name: Test Windows Chocolatey Package + runs-on: windows-2019 + defaults: + run: + shell: pwsh + env: + VERSION_BUILD: ${{ inputs.version }} + VERSION_MAJOR: ${{ inputs.major-version }} + steps: + + - name: Install cf cli package + run: choco install cloudfoundry-cli --version $env:VERSION_BUILD + + - name: Print Chocolatey CF CLI Versions + run: | + cd 'C:/ProgramData/chocolatey/lib/cloudfoundry-cli/tools' + ./cf -v + Invoke-Expression "./cf$env:VERSION_MAJOR -v" + + - name: Test Chocolatey Version Match + run: | + cd 'C:/ProgramData/chocolatey/lib/cloudfoundry-cli/tools' + $found = (./cf -v | Select-String "$env:VERSION_BUILD") + if ($null -eq $found) { + Write-Error "CF CLI version $env:VERSION_BUILD was not found" -ErrorAction Stop + } + + +# vim: set sw=2 ts=2 sts=2 et tw=78 foldlevel=2 fdm=indent nospell: From c5e7762f1b4012025ab91704d735833a8cf4e44f Mon Sep 17 00:00:00 2001 From: Johannes Dillmann Date: Mon, 18 Nov 2024 16:04:53 +0100 Subject: [PATCH 13/21] v8 downports of Cloud Native Buildpacks lifecycle support (#3281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add cnb lifecycle type * Show buildpack summary for cnb lifecycle * Add support for providing credentials for Cloud Native Buildpacks * Add cnb related integration tests and cats configuration * Enable diego_cnb feature flag in integration tests * Use new JS hello world app for cnb integration * Ensure CAPI version when using CNB lifecycle --------- Co-authored-by: João Pereira Co-authored-by: Johannes Dillmann Co-authored-by: Nicolas Bender Co-authored-by: Pavel Busko Co-authored-by: Ralf Pannemans --- actor/v7action/application.go | 1 + actor/v7pushaction/actor.go | 3 + actor/v7pushaction/create_push_plans.go | 12 + actor/v7pushaction/create_push_plans_test.go | 22 +- .../handle_cnb_credentials_override.go | 23 + .../handle_cnb_credentials_override_test.go | 66 +++ .../v7pushaction/handle_lifecycle_override.go | 19 + actor/v7pushaction/push_plan.go | 2 + api/cloudcontroller/ccv3/application_test.go | 11 + .../ccv3/constant/application.go | 3 + .../ccversion/minimum_version.go | 2 + cf/commands/application/apps.go | 2 +- command/commandfakes/fake_config.go | 479 ++++++++++++------ command/config.go | 1 + command/v7/create_app_command.go | 41 +- command/v7/create_app_command_test.go | 41 ++ command/v7/push_command.go | 74 ++- command/v7/push_command_test.go | 86 ++++ command/v7/shared/app_summary_displayer.go | 33 +- command/v7/shared/manifest_diff_displayer.go | 10 + .../v7/shared/manifest_diff_displayer_test.go | 32 ++ integration/assets/js-hello/index.js | 12 + integration/assets/js-hello/package.json | 8 + integration/helpers/app.go | 5 + .../commonisolated/common_isolated_setup.go | 1 + .../experimental/experimental_suite_test.go | 1 + .../shared/global/global_suite_test.go | 1 + integration/v7/global/global_suite_test.go | 1 + integration/v7/isolated/app_command_test.go | 16 + .../v7/isolated/create_app_command_test.go | 16 +- integration/v7/push/help_test.go | 1 + integration/v7/push/push_suite_test.go | 1 + integration/v7/push/tasks_test.go | 5 +- resources/application_resource.go | 16 +- util/configv3/env.go | 17 + util/configv3/load_config.go | 1 + util/manifestparser/application.go | 33 +- 37 files changed, 876 insertions(+), 222 deletions(-) create mode 100644 actor/v7pushaction/handle_cnb_credentials_override.go create mode 100644 actor/v7pushaction/handle_cnb_credentials_override_test.go create mode 100644 actor/v7pushaction/handle_lifecycle_override.go create mode 100644 integration/assets/js-hello/index.js create mode 100644 integration/assets/js-hello/package.json diff --git a/actor/v7action/application.go b/actor/v7action/application.go index 7d1c1fb2dca..e86ca01c34a 100644 --- a/actor/v7action/application.go +++ b/actor/v7action/application.go @@ -162,6 +162,7 @@ func (actor Actor) CreateApplicationInSpace(app resources.Application, spaceGUID LifecycleBuildpacks: app.LifecycleBuildpacks, StackName: app.StackName, Name: app.Name, + Credentials: app.Credentials, SpaceGUID: spaceGUID, }) diff --git a/actor/v7pushaction/actor.go b/actor/v7pushaction/actor.go index 829b64e2a19..4d2b2822cf2 100644 --- a/actor/v7pushaction/actor.go +++ b/actor/v7pushaction/actor.go @@ -42,6 +42,9 @@ func NewActor(v3Actor V7Actor, sharedActor SharedActor) *Actor { HandleInstancesOverride, HandleStartCommandOverride, + HandleCNBCredentialsOverride, + + HandleLifecycleOverride, // Type must come before endpoint because endpoint validates against type HandleHealthCheckTypeOverride, diff --git a/actor/v7pushaction/create_push_plans.go b/actor/v7pushaction/create_push_plans.go index 0b9efcf2af2..7c656d05063 100644 --- a/actor/v7pushaction/create_push_plans.go +++ b/actor/v7pushaction/create_push_plans.go @@ -31,6 +31,18 @@ func (actor Actor) CreatePushPlans( BitsPath: manifestApplication.Path, } + if manifestApplication.Lifecycle != "" { + plan.Application.LifecycleType = manifestApplication.Lifecycle + } + + if overrides.Lifecycle != "" { + plan.Application.LifecycleType = overrides.Lifecycle + } + + if overrides.CNBCredentials != nil { + plan.Application.Credentials = overrides.CNBCredentials + } + if manifestApplication.Docker != nil { plan.DockerImageCredentials = v7action.DockerImageCredentials{ Path: manifestApplication.Docker.Image, diff --git a/actor/v7pushaction/create_push_plans_test.go b/actor/v7pushaction/create_push_plans_test.go index 871026c3adb..9b8040935a0 100644 --- a/actor/v7pushaction/create_push_plans_test.go +++ b/actor/v7pushaction/create_push_plans_test.go @@ -41,7 +41,7 @@ var _ = Describe("CreatePushPlans", func() { manifest = manifestparser.Manifest{ Applications: []manifestparser.Application{ - {Name: "name-1", Path: "path1"}, + {Name: "name-1", Path: "path1", Lifecycle: "cnb"}, {Name: "name-2", Path: "path2", Docker: &manifestparser.Docker{Image: "image", Username: "uname"}}, }, } @@ -49,6 +49,9 @@ var _ = Describe("CreatePushPlans", func() { spaceGUID = "space" flagOverrides = FlagOverrides{ DockerPassword: "passwd", + CNBCredentials: map[string]interface{}{ + "foo": "bar", + }, } testUpdatePlanCount = 0 @@ -120,6 +123,10 @@ var _ = Describe("CreatePushPlans", func() { Expect(pushPlans[0].DockerImageCredentials.Username).To(Equal("")) Expect(pushPlans[0].DockerImageCredentials.Password).To(Equal("")) Expect(pushPlans[0].BitsPath).To(Equal("path1")) + Expect(pushPlans[0].Application.LifecycleType).To(BeEquivalentTo("cnb")) + Expect(pushPlans[0].Application.Credentials).To(Equal(map[string]interface{}{ + "foo": "bar", + })) Expect(pushPlans[1].Application.Name).To(Equal("name-2")) Expect(pushPlans[1].Application.GUID).To(Equal("app-guid-2")) Expect(pushPlans[1].SpaceGUID).To(Equal(spaceGUID)) @@ -128,7 +135,20 @@ var _ = Describe("CreatePushPlans", func() { Expect(pushPlans[1].DockerImageCredentials.Username).To(Equal("uname")) Expect(pushPlans[1].DockerImageCredentials.Password).To(Equal("passwd")) Expect(pushPlans[1].BitsPath).To(Equal("path2")) + Expect(pushPlans[1].Application.LifecycleType).To(BeEquivalentTo("")) }) + }) + When("lifecycle is overwritten", func() { + BeforeEach(func() { + flagOverrides = FlagOverrides{ + Lifecycle: "buildpack", + } + }) + + It("uses the lifecycle from the command line", func() { + Expect(pushPlans[0].Application.LifecycleType).To(BeEquivalentTo("buildpack")) + }) }) + }) diff --git a/actor/v7pushaction/handle_cnb_credentials_override.go b/actor/v7pushaction/handle_cnb_credentials_override.go new file mode 100644 index 00000000000..8fa212aab4b --- /dev/null +++ b/actor/v7pushaction/handle_cnb_credentials_override.go @@ -0,0 +1,23 @@ +package v7pushaction + +import ( + "code.cloudfoundry.org/cli/command/translatableerror" + "code.cloudfoundry.org/cli/util/manifestparser" +) + +func HandleCNBCredentialsOverride(manifest manifestparser.Manifest, overrides FlagOverrides) (manifestparser.Manifest, error) { + if overrides.CNBCredentials != nil { + if manifest.ContainsMultipleApps() { + return manifest, translatableerror.CommandLineArgsWithMultipleAppsError{} + } + + app := manifest.GetFirstApp() + if app.RemainingManifestFields == nil { + app.RemainingManifestFields = map[string]interface{}{} + } + + app.RemainingManifestFields["cnb-credentials"] = overrides.CNBCredentials + } + + return manifest, nil +} diff --git a/actor/v7pushaction/handle_cnb_credentials_override_test.go b/actor/v7pushaction/handle_cnb_credentials_override_test.go new file mode 100644 index 00000000000..87a1117de08 --- /dev/null +++ b/actor/v7pushaction/handle_cnb_credentials_override_test.go @@ -0,0 +1,66 @@ +package v7pushaction_test + +import ( + . "code.cloudfoundry.org/cli/actor/v7pushaction" + "code.cloudfoundry.org/cli/util/manifestparser" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("HandleCNBCredentialsOverride", func() { + var ( + originalManifest manifestparser.Manifest + transformedManifest manifestparser.Manifest + overrides FlagOverrides + executeErr error + ) + + BeforeEach(func() { + originalManifest = manifestparser.Manifest{ + Applications: []manifestparser.Application{{}}, + } + overrides = FlagOverrides{} + }) + + JustBeforeEach(func() { + transformedManifest, executeErr = HandleCNBCredentialsOverride(originalManifest, overrides) + }) + + When("the cnb credentials are present", func() { + BeforeEach(func() { + overrides.CNBCredentials = map[string]interface{}{ + "foo": "bar", + } + }) + + It("add it to the raw manifest", func() { + Expect(executeErr).NotTo(HaveOccurred()) + Expect(transformedManifest).To(Equal(manifestparser.Manifest{ + Applications: []manifestparser.Application{{ + RemainingManifestFields: map[string]interface{}{ + "cnb-credentials": map[string]interface{}{ + "foo": "bar", + }, + }, + }}, + })) + }) + + }) + + When("the credentials are not present", func() { + BeforeEach(func() { + overrides.CNBCredentials = nil + }) + + It("does not add it to the raw manifest", func() { + Expect(executeErr).NotTo(HaveOccurred()) + Expect(transformedManifest).To(Equal(manifestparser.Manifest{ + Applications: []manifestparser.Application{{}}, + })) + + }) + + }) +}) diff --git a/actor/v7pushaction/handle_lifecycle_override.go b/actor/v7pushaction/handle_lifecycle_override.go new file mode 100644 index 00000000000..005aa659029 --- /dev/null +++ b/actor/v7pushaction/handle_lifecycle_override.go @@ -0,0 +1,19 @@ +package v7pushaction + +import ( + "code.cloudfoundry.org/cli/command/translatableerror" + "code.cloudfoundry.org/cli/util/manifestparser" +) + +func HandleLifecycleOverride(manifest manifestparser.Manifest, overrides FlagOverrides) (manifestparser.Manifest, error) { + if overrides.Lifecycle != "" { + if manifest.ContainsMultipleApps() { + return manifest, translatableerror.CommandLineArgsWithMultipleAppsError{} + } + + app := manifest.GetFirstApp() + app.Lifecycle = overrides.Lifecycle + } + + return manifest, nil +} diff --git a/actor/v7pushaction/push_plan.go b/actor/v7pushaction/push_plan.go index 876a8ec2259..dc4a181e2b2 100644 --- a/actor/v7pushaction/push_plan.go +++ b/actor/v7pushaction/push_plan.go @@ -43,6 +43,7 @@ type FlagOverrides struct { DockerImage string DockerPassword string DockerUsername string + CNBCredentials map[string]interface{} HealthCheckEndpoint string HealthCheckTimeout int64 HealthCheckType constant.HealthCheckType @@ -62,6 +63,7 @@ type FlagOverrides struct { NoManifest bool Task bool LogRateLimit string + Lifecycle constant.AppLifecycleType } func (state PushPlan) String() string { diff --git a/api/cloudcontroller/ccv3/application_test.go b/api/cloudcontroller/ccv3/application_test.go index 467c8548722..46002b20b09 100644 --- a/api/cloudcontroller/ccv3/application_test.go +++ b/api/cloudcontroller/ccv3/application_test.go @@ -96,6 +96,17 @@ var _ = Describe("Application", func() { }) }) + When("lifecycle type cnb is provided", func() { + BeforeEach(func() { + app.LifecycleType = constant.AppLifecycleTypeCNB + app.LifecycleBuildpacks = []string{"docker://nodejs"} + }) + + It("sets the lifecycle buildpack to be empty in the JSON", func() { + Expect(string(appBytes)).To(MatchJSON(`{"lifecycle":{"data":{"buildpacks":["docker://nodejs"]},"type":"cnb"}}`)) + }) + }) + When("null buildpack is provided", func() { BeforeEach(func() { app.LifecycleBuildpacks = []string{"null"} diff --git a/api/cloudcontroller/ccv3/constant/application.go b/api/cloudcontroller/ccv3/constant/application.go index b0acd644dc0..dca0b70af39 100644 --- a/api/cloudcontroller/ccv3/constant/application.go +++ b/api/cloudcontroller/ccv3/constant/application.go @@ -9,6 +9,9 @@ const ( // AppLifecycleTypeDocker will pull a docker image from a registry to run an // app. AppLifecycleTypeDocker AppLifecycleType = "docker" + // AppLifecycleTypeCNB will use a droplet (created with cloud native buildpacks) + // and a rootfs to run the app. + AppLifecycleTypeCNB AppLifecycleType = "cnb" ) // ApplicationAction represents the action being taken on an application diff --git a/api/cloudcontroller/ccversion/minimum_version.go b/api/cloudcontroller/ccversion/minimum_version.go index 5158ab18f06..a0092171205 100644 --- a/api/cloudcontroller/ccversion/minimum_version.go +++ b/api/cloudcontroller/ccversion/minimum_version.go @@ -15,4 +15,6 @@ const ( MinVersionSpaceSupporterV3 = "3.104.0" MinVersionLogRateLimitingV3 = "3.124.0" // TODO: update this when we have a CAPI release + + MinVersionCNB = "3.168.0" ) diff --git a/cf/commands/application/apps.go b/cf/commands/application/apps.go index d77b38fff28..e246f9ff09b 100644 --- a/cf/commands/application/apps.go +++ b/cf/commands/application/apps.go @@ -7,7 +7,7 @@ import ( "code.cloudfoundry.org/cli/cf/flags" . "code.cloudfoundry.org/cli/cf/i18n" "code.cloudfoundry.org/cli/cf/models" - "code.cloudfoundry.org/cli/plugin/models" + plugin_models "code.cloudfoundry.org/cli/plugin/models" "code.cloudfoundry.org/cli/cf/api" "code.cloudfoundry.org/cli/cf/configuration/coreconfig" diff --git a/command/commandfakes/fake_config.go b/command/commandfakes/fake_config.go index 4e94d9f543c..2b7f1fe4014 100644 --- a/command/commandfakes/fake_config.go +++ b/command/commandfakes/fake_config.go @@ -91,6 +91,18 @@ type FakeConfig struct { cFUsernameReturnsOnCall map[int]struct { result1 string } + CNBCredentialsStub func() (map[string]interface{}, error) + cNBCredentialsMutex sync.RWMutex + cNBCredentialsArgsForCall []struct { + } + cNBCredentialsReturns struct { + result1 map[string]interface{} + result2 error + } + cNBCredentialsReturnsOnCall map[int]struct { + result1 map[string]interface{} + result2 error + } ColorEnabledStub func() configv3.ColorSetting colorEnabledMutex sync.RWMutex colorEnabledArgsForCall []struct { @@ -636,15 +648,16 @@ func (fake *FakeConfig) APIVersion() string { ret, specificReturn := fake.aPIVersionReturnsOnCall[len(fake.aPIVersionArgsForCall)] fake.aPIVersionArgsForCall = append(fake.aPIVersionArgsForCall, struct { }{}) + stub := fake.APIVersionStub + fakeReturns := fake.aPIVersionReturns fake.recordInvocation("APIVersion", []interface{}{}) fake.aPIVersionMutex.Unlock() - if fake.APIVersionStub != nil { - return fake.APIVersionStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.aPIVersionReturns return fakeReturns.result1 } @@ -688,15 +701,16 @@ func (fake *FakeConfig) AccessToken() string { ret, specificReturn := fake.accessTokenReturnsOnCall[len(fake.accessTokenArgsForCall)] fake.accessTokenArgsForCall = append(fake.accessTokenArgsForCall, struct { }{}) + stub := fake.AccessTokenStub + fakeReturns := fake.accessTokenReturns fake.recordInvocation("AccessToken", []interface{}{}) fake.accessTokenMutex.Unlock() - if fake.AccessTokenStub != nil { - return fake.AccessTokenStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.accessTokenReturns return fakeReturns.result1 } @@ -740,9 +754,10 @@ func (fake *FakeConfig) AddPlugin(arg1 configv3.Plugin) { fake.addPluginArgsForCall = append(fake.addPluginArgsForCall, struct { arg1 configv3.Plugin }{arg1}) + stub := fake.AddPluginStub fake.recordInvocation("AddPlugin", []interface{}{arg1}) fake.addPluginMutex.Unlock() - if fake.AddPluginStub != nil { + if stub != nil { fake.AddPluginStub(arg1) } } @@ -772,9 +787,10 @@ func (fake *FakeConfig) AddPluginRepository(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.AddPluginRepositoryStub fake.recordInvocation("AddPluginRepository", []interface{}{arg1, arg2}) fake.addPluginRepositoryMutex.Unlock() - if fake.AddPluginRepositoryStub != nil { + if stub != nil { fake.AddPluginRepositoryStub(arg1, arg2) } } @@ -803,15 +819,16 @@ func (fake *FakeConfig) AuthorizationEndpoint() string { ret, specificReturn := fake.authorizationEndpointReturnsOnCall[len(fake.authorizationEndpointArgsForCall)] fake.authorizationEndpointArgsForCall = append(fake.authorizationEndpointArgsForCall, struct { }{}) + stub := fake.AuthorizationEndpointStub + fakeReturns := fake.authorizationEndpointReturns fake.recordInvocation("AuthorizationEndpoint", []interface{}{}) fake.authorizationEndpointMutex.Unlock() - if fake.AuthorizationEndpointStub != nil { - return fake.AuthorizationEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.authorizationEndpointReturns return fakeReturns.result1 } @@ -855,15 +872,16 @@ func (fake *FakeConfig) BinaryName() string { ret, specificReturn := fake.binaryNameReturnsOnCall[len(fake.binaryNameArgsForCall)] fake.binaryNameArgsForCall = append(fake.binaryNameArgsForCall, struct { }{}) + stub := fake.BinaryNameStub + fakeReturns := fake.binaryNameReturns fake.recordInvocation("BinaryName", []interface{}{}) fake.binaryNameMutex.Unlock() - if fake.BinaryNameStub != nil { - return fake.BinaryNameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.binaryNameReturns return fakeReturns.result1 } @@ -907,15 +925,16 @@ func (fake *FakeConfig) BinaryVersion() string { ret, specificReturn := fake.binaryVersionReturnsOnCall[len(fake.binaryVersionArgsForCall)] fake.binaryVersionArgsForCall = append(fake.binaryVersionArgsForCall, struct { }{}) + stub := fake.BinaryVersionStub + fakeReturns := fake.binaryVersionReturns fake.recordInvocation("BinaryVersion", []interface{}{}) fake.binaryVersionMutex.Unlock() - if fake.BinaryVersionStub != nil { - return fake.BinaryVersionStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.binaryVersionReturns return fakeReturns.result1 } @@ -959,15 +978,16 @@ func (fake *FakeConfig) CFPassword() string { ret, specificReturn := fake.cFPasswordReturnsOnCall[len(fake.cFPasswordArgsForCall)] fake.cFPasswordArgsForCall = append(fake.cFPasswordArgsForCall, struct { }{}) + stub := fake.CFPasswordStub + fakeReturns := fake.cFPasswordReturns fake.recordInvocation("CFPassword", []interface{}{}) fake.cFPasswordMutex.Unlock() - if fake.CFPasswordStub != nil { - return fake.CFPasswordStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.cFPasswordReturns return fakeReturns.result1 } @@ -1011,15 +1031,16 @@ func (fake *FakeConfig) CFUsername() string { ret, specificReturn := fake.cFUsernameReturnsOnCall[len(fake.cFUsernameArgsForCall)] fake.cFUsernameArgsForCall = append(fake.cFUsernameArgsForCall, struct { }{}) + stub := fake.CFUsernameStub + fakeReturns := fake.cFUsernameReturns fake.recordInvocation("CFUsername", []interface{}{}) fake.cFUsernameMutex.Unlock() - if fake.CFUsernameStub != nil { - return fake.CFUsernameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.cFUsernameReturns return fakeReturns.result1 } @@ -1058,20 +1079,77 @@ func (fake *FakeConfig) CFUsernameReturnsOnCall(i int, result1 string) { }{result1} } +func (fake *FakeConfig) CNBCredentials() (map[string]interface{}, error) { + fake.cNBCredentialsMutex.Lock() + ret, specificReturn := fake.cNBCredentialsReturnsOnCall[len(fake.cNBCredentialsArgsForCall)] + fake.cNBCredentialsArgsForCall = append(fake.cNBCredentialsArgsForCall, struct { + }{}) + stub := fake.CNBCredentialsStub + fakeReturns := fake.cNBCredentialsReturns + fake.recordInvocation("CNBCredentials", []interface{}{}) + fake.cNBCredentialsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeConfig) CNBCredentialsCallCount() int { + fake.cNBCredentialsMutex.RLock() + defer fake.cNBCredentialsMutex.RUnlock() + return len(fake.cNBCredentialsArgsForCall) +} + +func (fake *FakeConfig) CNBCredentialsCalls(stub func() (map[string]interface{}, error)) { + fake.cNBCredentialsMutex.Lock() + defer fake.cNBCredentialsMutex.Unlock() + fake.CNBCredentialsStub = stub +} + +func (fake *FakeConfig) CNBCredentialsReturns(result1 map[string]interface{}, result2 error) { + fake.cNBCredentialsMutex.Lock() + defer fake.cNBCredentialsMutex.Unlock() + fake.CNBCredentialsStub = nil + fake.cNBCredentialsReturns = struct { + result1 map[string]interface{} + result2 error + }{result1, result2} +} + +func (fake *FakeConfig) CNBCredentialsReturnsOnCall(i int, result1 map[string]interface{}, result2 error) { + fake.cNBCredentialsMutex.Lock() + defer fake.cNBCredentialsMutex.Unlock() + fake.CNBCredentialsStub = nil + if fake.cNBCredentialsReturnsOnCall == nil { + fake.cNBCredentialsReturnsOnCall = make(map[int]struct { + result1 map[string]interface{} + result2 error + }) + } + fake.cNBCredentialsReturnsOnCall[i] = struct { + result1 map[string]interface{} + result2 error + }{result1, result2} +} + func (fake *FakeConfig) ColorEnabled() configv3.ColorSetting { fake.colorEnabledMutex.Lock() ret, specificReturn := fake.colorEnabledReturnsOnCall[len(fake.colorEnabledArgsForCall)] fake.colorEnabledArgsForCall = append(fake.colorEnabledArgsForCall, struct { }{}) + stub := fake.ColorEnabledStub + fakeReturns := fake.colorEnabledReturns fake.recordInvocation("ColorEnabled", []interface{}{}) fake.colorEnabledMutex.Unlock() - if fake.ColorEnabledStub != nil { - return fake.ColorEnabledStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.colorEnabledReturns return fakeReturns.result1 } @@ -1115,15 +1193,16 @@ func (fake *FakeConfig) CurrentUser() (configv3.User, error) { ret, specificReturn := fake.currentUserReturnsOnCall[len(fake.currentUserArgsForCall)] fake.currentUserArgsForCall = append(fake.currentUserArgsForCall, struct { }{}) + stub := fake.CurrentUserStub + fakeReturns := fake.currentUserReturns fake.recordInvocation("CurrentUser", []interface{}{}) fake.currentUserMutex.Unlock() - if fake.CurrentUserStub != nil { - return fake.CurrentUserStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.currentUserReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1170,15 +1249,16 @@ func (fake *FakeConfig) CurrentUserName() (string, error) { ret, specificReturn := fake.currentUserNameReturnsOnCall[len(fake.currentUserNameArgsForCall)] fake.currentUserNameArgsForCall = append(fake.currentUserNameArgsForCall, struct { }{}) + stub := fake.CurrentUserNameStub + fakeReturns := fake.currentUserNameReturns fake.recordInvocation("CurrentUserName", []interface{}{}) fake.currentUserNameMutex.Unlock() - if fake.CurrentUserNameStub != nil { - return fake.CurrentUserNameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.currentUserNameReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1225,15 +1305,16 @@ func (fake *FakeConfig) DialTimeout() time.Duration { ret, specificReturn := fake.dialTimeoutReturnsOnCall[len(fake.dialTimeoutArgsForCall)] fake.dialTimeoutArgsForCall = append(fake.dialTimeoutArgsForCall, struct { }{}) + stub := fake.DialTimeoutStub + fakeReturns := fake.dialTimeoutReturns fake.recordInvocation("DialTimeout", []interface{}{}) fake.dialTimeoutMutex.Unlock() - if fake.DialTimeoutStub != nil { - return fake.DialTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.dialTimeoutReturns return fakeReturns.result1 } @@ -1277,15 +1358,16 @@ func (fake *FakeConfig) DockerPassword() string { ret, specificReturn := fake.dockerPasswordReturnsOnCall[len(fake.dockerPasswordArgsForCall)] fake.dockerPasswordArgsForCall = append(fake.dockerPasswordArgsForCall, struct { }{}) + stub := fake.DockerPasswordStub + fakeReturns := fake.dockerPasswordReturns fake.recordInvocation("DockerPassword", []interface{}{}) fake.dockerPasswordMutex.Unlock() - if fake.DockerPasswordStub != nil { - return fake.DockerPasswordStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.dockerPasswordReturns return fakeReturns.result1 } @@ -1329,15 +1411,16 @@ func (fake *FakeConfig) Experimental() bool { ret, specificReturn := fake.experimentalReturnsOnCall[len(fake.experimentalArgsForCall)] fake.experimentalArgsForCall = append(fake.experimentalArgsForCall, struct { }{}) + stub := fake.ExperimentalStub + fakeReturns := fake.experimentalReturns fake.recordInvocation("Experimental", []interface{}{}) fake.experimentalMutex.Unlock() - if fake.ExperimentalStub != nil { - return fake.ExperimentalStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.experimentalReturns return fakeReturns.result1 } @@ -1382,15 +1465,16 @@ func (fake *FakeConfig) GetPlugin(arg1 string) (configv3.Plugin, bool) { fake.getPluginArgsForCall = append(fake.getPluginArgsForCall, struct { arg1 string }{arg1}) + stub := fake.GetPluginStub + fakeReturns := fake.getPluginReturns fake.recordInvocation("GetPlugin", []interface{}{arg1}) fake.getPluginMutex.Unlock() - if fake.GetPluginStub != nil { - return fake.GetPluginStub(arg1) + if stub != nil { + return stub(arg1) } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.getPluginReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1445,15 +1529,16 @@ func (fake *FakeConfig) GetPluginCaseInsensitive(arg1 string) (configv3.Plugin, fake.getPluginCaseInsensitiveArgsForCall = append(fake.getPluginCaseInsensitiveArgsForCall, struct { arg1 string }{arg1}) + stub := fake.GetPluginCaseInsensitiveStub + fakeReturns := fake.getPluginCaseInsensitiveReturns fake.recordInvocation("GetPluginCaseInsensitive", []interface{}{arg1}) fake.getPluginCaseInsensitiveMutex.Unlock() - if fake.GetPluginCaseInsensitiveStub != nil { - return fake.GetPluginCaseInsensitiveStub(arg1) + if stub != nil { + return stub(arg1) } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.getPluginCaseInsensitiveReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1507,15 +1592,16 @@ func (fake *FakeConfig) HasTargetedOrganization() bool { ret, specificReturn := fake.hasTargetedOrganizationReturnsOnCall[len(fake.hasTargetedOrganizationArgsForCall)] fake.hasTargetedOrganizationArgsForCall = append(fake.hasTargetedOrganizationArgsForCall, struct { }{}) + stub := fake.HasTargetedOrganizationStub + fakeReturns := fake.hasTargetedOrganizationReturns fake.recordInvocation("HasTargetedOrganization", []interface{}{}) fake.hasTargetedOrganizationMutex.Unlock() - if fake.HasTargetedOrganizationStub != nil { - return fake.HasTargetedOrganizationStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.hasTargetedOrganizationReturns return fakeReturns.result1 } @@ -1559,15 +1645,16 @@ func (fake *FakeConfig) HasTargetedSpace() bool { ret, specificReturn := fake.hasTargetedSpaceReturnsOnCall[len(fake.hasTargetedSpaceArgsForCall)] fake.hasTargetedSpaceArgsForCall = append(fake.hasTargetedSpaceArgsForCall, struct { }{}) + stub := fake.HasTargetedSpaceStub + fakeReturns := fake.hasTargetedSpaceReturns fake.recordInvocation("HasTargetedSpace", []interface{}{}) fake.hasTargetedSpaceMutex.Unlock() - if fake.HasTargetedSpaceStub != nil { - return fake.HasTargetedSpaceStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.hasTargetedSpaceReturns return fakeReturns.result1 } @@ -1611,15 +1698,16 @@ func (fake *FakeConfig) IsCFOnK8s() bool { ret, specificReturn := fake.isCFOnK8sReturnsOnCall[len(fake.isCFOnK8sArgsForCall)] fake.isCFOnK8sArgsForCall = append(fake.isCFOnK8sArgsForCall, struct { }{}) + stub := fake.IsCFOnK8sStub + fakeReturns := fake.isCFOnK8sReturns fake.recordInvocation("IsCFOnK8s", []interface{}{}) fake.isCFOnK8sMutex.Unlock() - if fake.IsCFOnK8sStub != nil { - return fake.IsCFOnK8sStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.isCFOnK8sReturns return fakeReturns.result1 } @@ -1663,15 +1751,16 @@ func (fake *FakeConfig) IsTTY() bool { ret, specificReturn := fake.isTTYReturnsOnCall[len(fake.isTTYArgsForCall)] fake.isTTYArgsForCall = append(fake.isTTYArgsForCall, struct { }{}) + stub := fake.IsTTYStub + fakeReturns := fake.isTTYReturns fake.recordInvocation("IsTTY", []interface{}{}) fake.isTTYMutex.Unlock() - if fake.IsTTYStub != nil { - return fake.IsTTYStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.isTTYReturns return fakeReturns.result1 } @@ -1715,15 +1804,16 @@ func (fake *FakeConfig) Locale() string { ret, specificReturn := fake.localeReturnsOnCall[len(fake.localeArgsForCall)] fake.localeArgsForCall = append(fake.localeArgsForCall, struct { }{}) + stub := fake.LocaleStub + fakeReturns := fake.localeReturns fake.recordInvocation("Locale", []interface{}{}) fake.localeMutex.Unlock() - if fake.LocaleStub != nil { - return fake.LocaleStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.localeReturns return fakeReturns.result1 } @@ -1767,15 +1857,16 @@ func (fake *FakeConfig) LogCacheEndpoint() string { ret, specificReturn := fake.logCacheEndpointReturnsOnCall[len(fake.logCacheEndpointArgsForCall)] fake.logCacheEndpointArgsForCall = append(fake.logCacheEndpointArgsForCall, struct { }{}) + stub := fake.LogCacheEndpointStub + fakeReturns := fake.logCacheEndpointReturns fake.recordInvocation("LogCacheEndpoint", []interface{}{}) fake.logCacheEndpointMutex.Unlock() - if fake.LogCacheEndpointStub != nil { - return fake.LogCacheEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.logCacheEndpointReturns return fakeReturns.result1 } @@ -1819,15 +1910,16 @@ func (fake *FakeConfig) MinCLIVersion() string { ret, specificReturn := fake.minCLIVersionReturnsOnCall[len(fake.minCLIVersionArgsForCall)] fake.minCLIVersionArgsForCall = append(fake.minCLIVersionArgsForCall, struct { }{}) + stub := fake.MinCLIVersionStub + fakeReturns := fake.minCLIVersionReturns fake.recordInvocation("MinCLIVersion", []interface{}{}) fake.minCLIVersionMutex.Unlock() - if fake.MinCLIVersionStub != nil { - return fake.MinCLIVersionStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.minCLIVersionReturns return fakeReturns.result1 } @@ -1871,15 +1963,16 @@ func (fake *FakeConfig) NOAARequestRetryCount() int { ret, specificReturn := fake.nOAARequestRetryCountReturnsOnCall[len(fake.nOAARequestRetryCountArgsForCall)] fake.nOAARequestRetryCountArgsForCall = append(fake.nOAARequestRetryCountArgsForCall, struct { }{}) + stub := fake.NOAARequestRetryCountStub + fakeReturns := fake.nOAARequestRetryCountReturns fake.recordInvocation("NOAARequestRetryCount", []interface{}{}) fake.nOAARequestRetryCountMutex.Unlock() - if fake.NOAARequestRetryCountStub != nil { - return fake.NOAARequestRetryCountStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.nOAARequestRetryCountReturns return fakeReturns.result1 } @@ -1923,15 +2016,16 @@ func (fake *FakeConfig) NetworkPolicyV1Endpoint() string { ret, specificReturn := fake.networkPolicyV1EndpointReturnsOnCall[len(fake.networkPolicyV1EndpointArgsForCall)] fake.networkPolicyV1EndpointArgsForCall = append(fake.networkPolicyV1EndpointArgsForCall, struct { }{}) + stub := fake.NetworkPolicyV1EndpointStub + fakeReturns := fake.networkPolicyV1EndpointReturns fake.recordInvocation("NetworkPolicyV1Endpoint", []interface{}{}) fake.networkPolicyV1EndpointMutex.Unlock() - if fake.NetworkPolicyV1EndpointStub != nil { - return fake.NetworkPolicyV1EndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.networkPolicyV1EndpointReturns return fakeReturns.result1 } @@ -1975,15 +2069,16 @@ func (fake *FakeConfig) OverallPollingTimeout() time.Duration { ret, specificReturn := fake.overallPollingTimeoutReturnsOnCall[len(fake.overallPollingTimeoutArgsForCall)] fake.overallPollingTimeoutArgsForCall = append(fake.overallPollingTimeoutArgsForCall, struct { }{}) + stub := fake.OverallPollingTimeoutStub + fakeReturns := fake.overallPollingTimeoutReturns fake.recordInvocation("OverallPollingTimeout", []interface{}{}) fake.overallPollingTimeoutMutex.Unlock() - if fake.OverallPollingTimeoutStub != nil { - return fake.OverallPollingTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.overallPollingTimeoutReturns return fakeReturns.result1 } @@ -2027,15 +2122,16 @@ func (fake *FakeConfig) PluginHome() string { ret, specificReturn := fake.pluginHomeReturnsOnCall[len(fake.pluginHomeArgsForCall)] fake.pluginHomeArgsForCall = append(fake.pluginHomeArgsForCall, struct { }{}) + stub := fake.PluginHomeStub + fakeReturns := fake.pluginHomeReturns fake.recordInvocation("PluginHome", []interface{}{}) fake.pluginHomeMutex.Unlock() - if fake.PluginHomeStub != nil { - return fake.PluginHomeStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pluginHomeReturns return fakeReturns.result1 } @@ -2079,15 +2175,16 @@ func (fake *FakeConfig) PluginRepositories() []configv3.PluginRepository { ret, specificReturn := fake.pluginRepositoriesReturnsOnCall[len(fake.pluginRepositoriesArgsForCall)] fake.pluginRepositoriesArgsForCall = append(fake.pluginRepositoriesArgsForCall, struct { }{}) + stub := fake.PluginRepositoriesStub + fakeReturns := fake.pluginRepositoriesReturns fake.recordInvocation("PluginRepositories", []interface{}{}) fake.pluginRepositoriesMutex.Unlock() - if fake.PluginRepositoriesStub != nil { - return fake.PluginRepositoriesStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pluginRepositoriesReturns return fakeReturns.result1 } @@ -2131,15 +2228,16 @@ func (fake *FakeConfig) Plugins() []configv3.Plugin { ret, specificReturn := fake.pluginsReturnsOnCall[len(fake.pluginsArgsForCall)] fake.pluginsArgsForCall = append(fake.pluginsArgsForCall, struct { }{}) + stub := fake.PluginsStub + fakeReturns := fake.pluginsReturns fake.recordInvocation("Plugins", []interface{}{}) fake.pluginsMutex.Unlock() - if fake.PluginsStub != nil { - return fake.PluginsStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pluginsReturns return fakeReturns.result1 } @@ -2183,15 +2281,16 @@ func (fake *FakeConfig) PollingInterval() time.Duration { ret, specificReturn := fake.pollingIntervalReturnsOnCall[len(fake.pollingIntervalArgsForCall)] fake.pollingIntervalArgsForCall = append(fake.pollingIntervalArgsForCall, struct { }{}) + stub := fake.PollingIntervalStub + fakeReturns := fake.pollingIntervalReturns fake.recordInvocation("PollingInterval", []interface{}{}) fake.pollingIntervalMutex.Unlock() - if fake.PollingIntervalStub != nil { - return fake.PollingIntervalStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pollingIntervalReturns return fakeReturns.result1 } @@ -2235,15 +2334,16 @@ func (fake *FakeConfig) RefreshToken() string { ret, specificReturn := fake.refreshTokenReturnsOnCall[len(fake.refreshTokenArgsForCall)] fake.refreshTokenArgsForCall = append(fake.refreshTokenArgsForCall, struct { }{}) + stub := fake.RefreshTokenStub + fakeReturns := fake.refreshTokenReturns fake.recordInvocation("RefreshToken", []interface{}{}) fake.refreshTokenMutex.Unlock() - if fake.RefreshTokenStub != nil { - return fake.RefreshTokenStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.refreshTokenReturns return fakeReturns.result1 } @@ -2287,9 +2387,10 @@ func (fake *FakeConfig) RemovePlugin(arg1 string) { fake.removePluginArgsForCall = append(fake.removePluginArgsForCall, struct { arg1 string }{arg1}) + stub := fake.RemovePluginStub fake.recordInvocation("RemovePlugin", []interface{}{arg1}) fake.removePluginMutex.Unlock() - if fake.RemovePluginStub != nil { + if stub != nil { fake.RemovePluginStub(arg1) } } @@ -2318,15 +2419,16 @@ func (fake *FakeConfig) RequestRetryCount() int { ret, specificReturn := fake.requestRetryCountReturnsOnCall[len(fake.requestRetryCountArgsForCall)] fake.requestRetryCountArgsForCall = append(fake.requestRetryCountArgsForCall, struct { }{}) + stub := fake.RequestRetryCountStub + fakeReturns := fake.requestRetryCountReturns fake.recordInvocation("RequestRetryCount", []interface{}{}) fake.requestRetryCountMutex.Unlock() - if fake.RequestRetryCountStub != nil { - return fake.RequestRetryCountStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.requestRetryCountReturns return fakeReturns.result1 } @@ -2370,15 +2472,16 @@ func (fake *FakeConfig) RoutingEndpoint() string { ret, specificReturn := fake.routingEndpointReturnsOnCall[len(fake.routingEndpointArgsForCall)] fake.routingEndpointArgsForCall = append(fake.routingEndpointArgsForCall, struct { }{}) + stub := fake.RoutingEndpointStub + fakeReturns := fake.routingEndpointReturns fake.recordInvocation("RoutingEndpoint", []interface{}{}) fake.routingEndpointMutex.Unlock() - if fake.RoutingEndpointStub != nil { - return fake.RoutingEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.routingEndpointReturns return fakeReturns.result1 } @@ -2422,15 +2525,16 @@ func (fake *FakeConfig) SSHOAuthClient() string { ret, specificReturn := fake.sSHOAuthClientReturnsOnCall[len(fake.sSHOAuthClientArgsForCall)] fake.sSHOAuthClientArgsForCall = append(fake.sSHOAuthClientArgsForCall, struct { }{}) + stub := fake.SSHOAuthClientStub + fakeReturns := fake.sSHOAuthClientReturns fake.recordInvocation("SSHOAuthClient", []interface{}{}) fake.sSHOAuthClientMutex.Unlock() - if fake.SSHOAuthClientStub != nil { - return fake.SSHOAuthClientStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.sSHOAuthClientReturns return fakeReturns.result1 } @@ -2474,9 +2578,10 @@ func (fake *FakeConfig) SetAccessToken(arg1 string) { fake.setAccessTokenArgsForCall = append(fake.setAccessTokenArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetAccessTokenStub fake.recordInvocation("SetAccessToken", []interface{}{arg1}) fake.setAccessTokenMutex.Unlock() - if fake.SetAccessTokenStub != nil { + if stub != nil { fake.SetAccessTokenStub(arg1) } } @@ -2505,9 +2610,10 @@ func (fake *FakeConfig) SetAsyncTimeout(arg1 int) { fake.setAsyncTimeoutArgsForCall = append(fake.setAsyncTimeoutArgsForCall, struct { arg1 int }{arg1}) + stub := fake.SetAsyncTimeoutStub fake.recordInvocation("SetAsyncTimeout", []interface{}{arg1}) fake.setAsyncTimeoutMutex.Unlock() - if fake.SetAsyncTimeoutStub != nil { + if stub != nil { fake.SetAsyncTimeoutStub(arg1) } } @@ -2536,9 +2642,10 @@ func (fake *FakeConfig) SetColorEnabled(arg1 string) { fake.setColorEnabledArgsForCall = append(fake.setColorEnabledArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetColorEnabledStub fake.recordInvocation("SetColorEnabled", []interface{}{arg1}) fake.setColorEnabledMutex.Unlock() - if fake.SetColorEnabledStub != nil { + if stub != nil { fake.SetColorEnabledStub(arg1) } } @@ -2567,9 +2674,10 @@ func (fake *FakeConfig) SetKubernetesAuthInfo(arg1 string) { fake.setKubernetesAuthInfoArgsForCall = append(fake.setKubernetesAuthInfoArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetKubernetesAuthInfoStub fake.recordInvocation("SetKubernetesAuthInfo", []interface{}{arg1}) fake.setKubernetesAuthInfoMutex.Unlock() - if fake.SetKubernetesAuthInfoStub != nil { + if stub != nil { fake.SetKubernetesAuthInfoStub(arg1) } } @@ -2598,9 +2706,10 @@ func (fake *FakeConfig) SetLocale(arg1 string) { fake.setLocaleArgsForCall = append(fake.setLocaleArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetLocaleStub fake.recordInvocation("SetLocale", []interface{}{arg1}) fake.setLocaleMutex.Unlock() - if fake.SetLocaleStub != nil { + if stub != nil { fake.SetLocaleStub(arg1) } } @@ -2629,9 +2738,10 @@ func (fake *FakeConfig) SetMinCLIVersion(arg1 string) { fake.setMinCLIVersionArgsForCall = append(fake.setMinCLIVersionArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetMinCLIVersionStub fake.recordInvocation("SetMinCLIVersion", []interface{}{arg1}) fake.setMinCLIVersionMutex.Unlock() - if fake.SetMinCLIVersionStub != nil { + if stub != nil { fake.SetMinCLIVersionStub(arg1) } } @@ -2661,9 +2771,10 @@ func (fake *FakeConfig) SetOrganizationInformation(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.SetOrganizationInformationStub fake.recordInvocation("SetOrganizationInformation", []interface{}{arg1, arg2}) fake.setOrganizationInformationMutex.Unlock() - if fake.SetOrganizationInformationStub != nil { + if stub != nil { fake.SetOrganizationInformationStub(arg1, arg2) } } @@ -2692,9 +2803,10 @@ func (fake *FakeConfig) SetRefreshToken(arg1 string) { fake.setRefreshTokenArgsForCall = append(fake.setRefreshTokenArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetRefreshTokenStub fake.recordInvocation("SetRefreshToken", []interface{}{arg1}) fake.setRefreshTokenMutex.Unlock() - if fake.SetRefreshTokenStub != nil { + if stub != nil { fake.SetRefreshTokenStub(arg1) } } @@ -2725,9 +2837,10 @@ func (fake *FakeConfig) SetSpaceInformation(arg1 string, arg2 string, arg3 bool) arg2 string arg3 bool }{arg1, arg2, arg3}) + stub := fake.SetSpaceInformationStub fake.recordInvocation("SetSpaceInformation", []interface{}{arg1, arg2, arg3}) fake.setSpaceInformationMutex.Unlock() - if fake.SetSpaceInformationStub != nil { + if stub != nil { fake.SetSpaceInformationStub(arg1, arg2, arg3) } } @@ -2756,9 +2869,10 @@ func (fake *FakeConfig) SetTargetInformation(arg1 configv3.TargetInformationArgs fake.setTargetInformationArgsForCall = append(fake.setTargetInformationArgsForCall, struct { arg1 configv3.TargetInformationArgs }{arg1}) + stub := fake.SetTargetInformationStub fake.recordInvocation("SetTargetInformation", []interface{}{arg1}) fake.setTargetInformationMutex.Unlock() - if fake.SetTargetInformationStub != nil { + if stub != nil { fake.SetTargetInformationStub(arg1) } } @@ -2789,9 +2903,10 @@ func (fake *FakeConfig) SetTokenInformation(arg1 string, arg2 string, arg3 strin arg2 string arg3 string }{arg1, arg2, arg3}) + stub := fake.SetTokenInformationStub fake.recordInvocation("SetTokenInformation", []interface{}{arg1, arg2, arg3}) fake.setTokenInformationMutex.Unlock() - if fake.SetTokenInformationStub != nil { + if stub != nil { fake.SetTokenInformationStub(arg1, arg2, arg3) } } @@ -2820,9 +2935,10 @@ func (fake *FakeConfig) SetTrace(arg1 string) { fake.setTraceArgsForCall = append(fake.setTraceArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetTraceStub fake.recordInvocation("SetTrace", []interface{}{arg1}) fake.setTraceMutex.Unlock() - if fake.SetTraceStub != nil { + if stub != nil { fake.SetTraceStub(arg1) } } @@ -2852,9 +2968,10 @@ func (fake *FakeConfig) SetUAAClientCredentials(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.SetUAAClientCredentialsStub fake.recordInvocation("SetUAAClientCredentials", []interface{}{arg1, arg2}) fake.setUAAClientCredentialsMutex.Unlock() - if fake.SetUAAClientCredentialsStub != nil { + if stub != nil { fake.SetUAAClientCredentialsStub(arg1, arg2) } } @@ -2883,9 +3000,10 @@ func (fake *FakeConfig) SetUAAEndpoint(arg1 string) { fake.setUAAEndpointArgsForCall = append(fake.setUAAEndpointArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetUAAEndpointStub fake.recordInvocation("SetUAAEndpoint", []interface{}{arg1}) fake.setUAAEndpointMutex.Unlock() - if fake.SetUAAEndpointStub != nil { + if stub != nil { fake.SetUAAEndpointStub(arg1) } } @@ -2914,9 +3032,10 @@ func (fake *FakeConfig) SetUAAGrantType(arg1 string) { fake.setUAAGrantTypeArgsForCall = append(fake.setUAAGrantTypeArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetUAAGrantTypeStub fake.recordInvocation("SetUAAGrantType", []interface{}{arg1}) fake.setUAAGrantTypeMutex.Unlock() - if fake.SetUAAGrantTypeStub != nil { + if stub != nil { fake.SetUAAGrantTypeStub(arg1) } } @@ -2945,15 +3064,16 @@ func (fake *FakeConfig) SkipSSLValidation() bool { ret, specificReturn := fake.skipSSLValidationReturnsOnCall[len(fake.skipSSLValidationArgsForCall)] fake.skipSSLValidationArgsForCall = append(fake.skipSSLValidationArgsForCall, struct { }{}) + stub := fake.SkipSSLValidationStub + fakeReturns := fake.skipSSLValidationReturns fake.recordInvocation("SkipSSLValidation", []interface{}{}) fake.skipSSLValidationMutex.Unlock() - if fake.SkipSSLValidationStub != nil { - return fake.SkipSSLValidationStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.skipSSLValidationReturns return fakeReturns.result1 } @@ -2997,15 +3117,16 @@ func (fake *FakeConfig) StagingTimeout() time.Duration { ret, specificReturn := fake.stagingTimeoutReturnsOnCall[len(fake.stagingTimeoutArgsForCall)] fake.stagingTimeoutArgsForCall = append(fake.stagingTimeoutArgsForCall, struct { }{}) + stub := fake.StagingTimeoutStub + fakeReturns := fake.stagingTimeoutReturns fake.recordInvocation("StagingTimeout", []interface{}{}) fake.stagingTimeoutMutex.Unlock() - if fake.StagingTimeoutStub != nil { - return fake.StagingTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.stagingTimeoutReturns return fakeReturns.result1 } @@ -3049,15 +3170,16 @@ func (fake *FakeConfig) StartupTimeout() time.Duration { ret, specificReturn := fake.startupTimeoutReturnsOnCall[len(fake.startupTimeoutArgsForCall)] fake.startupTimeoutArgsForCall = append(fake.startupTimeoutArgsForCall, struct { }{}) + stub := fake.StartupTimeoutStub + fakeReturns := fake.startupTimeoutReturns fake.recordInvocation("StartupTimeout", []interface{}{}) fake.startupTimeoutMutex.Unlock() - if fake.StartupTimeoutStub != nil { - return fake.StartupTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.startupTimeoutReturns return fakeReturns.result1 } @@ -3101,15 +3223,16 @@ func (fake *FakeConfig) Target() string { ret, specificReturn := fake.targetReturnsOnCall[len(fake.targetArgsForCall)] fake.targetArgsForCall = append(fake.targetArgsForCall, struct { }{}) + stub := fake.TargetStub + fakeReturns := fake.targetReturns fake.recordInvocation("Target", []interface{}{}) fake.targetMutex.Unlock() - if fake.TargetStub != nil { - return fake.TargetStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetReturns return fakeReturns.result1 } @@ -3153,15 +3276,16 @@ func (fake *FakeConfig) TargetedOrganization() configv3.Organization { ret, specificReturn := fake.targetedOrganizationReturnsOnCall[len(fake.targetedOrganizationArgsForCall)] fake.targetedOrganizationArgsForCall = append(fake.targetedOrganizationArgsForCall, struct { }{}) + stub := fake.TargetedOrganizationStub + fakeReturns := fake.targetedOrganizationReturns fake.recordInvocation("TargetedOrganization", []interface{}{}) fake.targetedOrganizationMutex.Unlock() - if fake.TargetedOrganizationStub != nil { - return fake.TargetedOrganizationStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetedOrganizationReturns return fakeReturns.result1 } @@ -3205,15 +3329,16 @@ func (fake *FakeConfig) TargetedOrganizationName() string { ret, specificReturn := fake.targetedOrganizationNameReturnsOnCall[len(fake.targetedOrganizationNameArgsForCall)] fake.targetedOrganizationNameArgsForCall = append(fake.targetedOrganizationNameArgsForCall, struct { }{}) + stub := fake.TargetedOrganizationNameStub + fakeReturns := fake.targetedOrganizationNameReturns fake.recordInvocation("TargetedOrganizationName", []interface{}{}) fake.targetedOrganizationNameMutex.Unlock() - if fake.TargetedOrganizationNameStub != nil { - return fake.TargetedOrganizationNameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetedOrganizationNameReturns return fakeReturns.result1 } @@ -3257,15 +3382,16 @@ func (fake *FakeConfig) TargetedSpace() configv3.Space { ret, specificReturn := fake.targetedSpaceReturnsOnCall[len(fake.targetedSpaceArgsForCall)] fake.targetedSpaceArgsForCall = append(fake.targetedSpaceArgsForCall, struct { }{}) + stub := fake.TargetedSpaceStub + fakeReturns := fake.targetedSpaceReturns fake.recordInvocation("TargetedSpace", []interface{}{}) fake.targetedSpaceMutex.Unlock() - if fake.TargetedSpaceStub != nil { - return fake.TargetedSpaceStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetedSpaceReturns return fakeReturns.result1 } @@ -3309,15 +3435,16 @@ func (fake *FakeConfig) TerminalWidth() int { ret, specificReturn := fake.terminalWidthReturnsOnCall[len(fake.terminalWidthArgsForCall)] fake.terminalWidthArgsForCall = append(fake.terminalWidthArgsForCall, struct { }{}) + stub := fake.TerminalWidthStub + fakeReturns := fake.terminalWidthReturns fake.recordInvocation("TerminalWidth", []interface{}{}) fake.terminalWidthMutex.Unlock() - if fake.TerminalWidthStub != nil { - return fake.TerminalWidthStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.terminalWidthReturns return fakeReturns.result1 } @@ -3361,15 +3488,16 @@ func (fake *FakeConfig) UAADisableKeepAlives() bool { ret, specificReturn := fake.uAADisableKeepAlivesReturnsOnCall[len(fake.uAADisableKeepAlivesArgsForCall)] fake.uAADisableKeepAlivesArgsForCall = append(fake.uAADisableKeepAlivesArgsForCall, struct { }{}) + stub := fake.UAADisableKeepAlivesStub + fakeReturns := fake.uAADisableKeepAlivesReturns fake.recordInvocation("UAADisableKeepAlives", []interface{}{}) fake.uAADisableKeepAlivesMutex.Unlock() - if fake.UAADisableKeepAlivesStub != nil { - return fake.UAADisableKeepAlivesStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAADisableKeepAlivesReturns return fakeReturns.result1 } @@ -3413,15 +3541,16 @@ func (fake *FakeConfig) UAAEndpoint() string { ret, specificReturn := fake.uAAEndpointReturnsOnCall[len(fake.uAAEndpointArgsForCall)] fake.uAAEndpointArgsForCall = append(fake.uAAEndpointArgsForCall, struct { }{}) + stub := fake.UAAEndpointStub + fakeReturns := fake.uAAEndpointReturns fake.recordInvocation("UAAEndpoint", []interface{}{}) fake.uAAEndpointMutex.Unlock() - if fake.UAAEndpointStub != nil { - return fake.UAAEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAEndpointReturns return fakeReturns.result1 } @@ -3465,15 +3594,16 @@ func (fake *FakeConfig) UAAGrantType() string { ret, specificReturn := fake.uAAGrantTypeReturnsOnCall[len(fake.uAAGrantTypeArgsForCall)] fake.uAAGrantTypeArgsForCall = append(fake.uAAGrantTypeArgsForCall, struct { }{}) + stub := fake.UAAGrantTypeStub + fakeReturns := fake.uAAGrantTypeReturns fake.recordInvocation("UAAGrantType", []interface{}{}) fake.uAAGrantTypeMutex.Unlock() - if fake.UAAGrantTypeStub != nil { - return fake.UAAGrantTypeStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAGrantTypeReturns return fakeReturns.result1 } @@ -3517,15 +3647,16 @@ func (fake *FakeConfig) UAAOAuthClient() string { ret, specificReturn := fake.uAAOAuthClientReturnsOnCall[len(fake.uAAOAuthClientArgsForCall)] fake.uAAOAuthClientArgsForCall = append(fake.uAAOAuthClientArgsForCall, struct { }{}) + stub := fake.UAAOAuthClientStub + fakeReturns := fake.uAAOAuthClientReturns fake.recordInvocation("UAAOAuthClient", []interface{}{}) fake.uAAOAuthClientMutex.Unlock() - if fake.UAAOAuthClientStub != nil { - return fake.UAAOAuthClientStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAOAuthClientReturns return fakeReturns.result1 } @@ -3569,15 +3700,16 @@ func (fake *FakeConfig) UAAOAuthClientSecret() string { ret, specificReturn := fake.uAAOAuthClientSecretReturnsOnCall[len(fake.uAAOAuthClientSecretArgsForCall)] fake.uAAOAuthClientSecretArgsForCall = append(fake.uAAOAuthClientSecretArgsForCall, struct { }{}) + stub := fake.UAAOAuthClientSecretStub + fakeReturns := fake.uAAOAuthClientSecretReturns fake.recordInvocation("UAAOAuthClientSecret", []interface{}{}) fake.uAAOAuthClientSecretMutex.Unlock() - if fake.UAAOAuthClientSecretStub != nil { - return fake.UAAOAuthClientSecretStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAOAuthClientSecretReturns return fakeReturns.result1 } @@ -3620,9 +3752,10 @@ func (fake *FakeConfig) UnsetOrganizationAndSpaceInformation() { fake.unsetOrganizationAndSpaceInformationMutex.Lock() fake.unsetOrganizationAndSpaceInformationArgsForCall = append(fake.unsetOrganizationAndSpaceInformationArgsForCall, struct { }{}) + stub := fake.UnsetOrganizationAndSpaceInformationStub fake.recordInvocation("UnsetOrganizationAndSpaceInformation", []interface{}{}) fake.unsetOrganizationAndSpaceInformationMutex.Unlock() - if fake.UnsetOrganizationAndSpaceInformationStub != nil { + if stub != nil { fake.UnsetOrganizationAndSpaceInformationStub() } } @@ -3643,9 +3776,10 @@ func (fake *FakeConfig) UnsetSpaceInformation() { fake.unsetSpaceInformationMutex.Lock() fake.unsetSpaceInformationArgsForCall = append(fake.unsetSpaceInformationArgsForCall, struct { }{}) + stub := fake.UnsetSpaceInformationStub fake.recordInvocation("UnsetSpaceInformation", []interface{}{}) fake.unsetSpaceInformationMutex.Unlock() - if fake.UnsetSpaceInformationStub != nil { + if stub != nil { fake.UnsetSpaceInformationStub() } } @@ -3666,9 +3800,10 @@ func (fake *FakeConfig) UnsetUserInformation() { fake.unsetUserInformationMutex.Lock() fake.unsetUserInformationArgsForCall = append(fake.unsetUserInformationArgsForCall, struct { }{}) + stub := fake.UnsetUserInformationStub fake.recordInvocation("UnsetUserInformation", []interface{}{}) fake.unsetUserInformationMutex.Unlock() - if fake.UnsetUserInformationStub != nil { + if stub != nil { fake.UnsetUserInformationStub() } } @@ -3691,9 +3826,10 @@ func (fake *FakeConfig) V7SetSpaceInformation(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.V7SetSpaceInformationStub fake.recordInvocation("V7SetSpaceInformation", []interface{}{arg1, arg2}) fake.v7SetSpaceInformationMutex.Unlock() - if fake.V7SetSpaceInformationStub != nil { + if stub != nil { fake.V7SetSpaceInformationStub(arg1, arg2) } } @@ -3722,15 +3858,16 @@ func (fake *FakeConfig) Verbose() (bool, []string) { ret, specificReturn := fake.verboseReturnsOnCall[len(fake.verboseArgsForCall)] fake.verboseArgsForCall = append(fake.verboseArgsForCall, struct { }{}) + stub := fake.VerboseStub + fakeReturns := fake.verboseReturns fake.recordInvocation("Verbose", []interface{}{}) fake.verboseMutex.Unlock() - if fake.VerboseStub != nil { - return fake.VerboseStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.verboseReturns return fakeReturns.result1, fakeReturns.result2 } @@ -3777,15 +3914,16 @@ func (fake *FakeConfig) WriteConfig() error { ret, specificReturn := fake.writeConfigReturnsOnCall[len(fake.writeConfigArgsForCall)] fake.writeConfigArgsForCall = append(fake.writeConfigArgsForCall, struct { }{}) + stub := fake.WriteConfigStub + fakeReturns := fake.writeConfigReturns fake.recordInvocation("WriteConfig", []interface{}{}) fake.writeConfigMutex.Unlock() - if fake.WriteConfigStub != nil { - return fake.WriteConfigStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.writeConfigReturns return fakeReturns.result1 } @@ -3829,15 +3967,16 @@ func (fake *FakeConfig) WritePluginConfig() error { ret, specificReturn := fake.writePluginConfigReturnsOnCall[len(fake.writePluginConfigArgsForCall)] fake.writePluginConfigArgsForCall = append(fake.writePluginConfigArgsForCall, struct { }{}) + stub := fake.WritePluginConfigStub + fakeReturns := fake.writePluginConfigReturns fake.recordInvocation("WritePluginConfig", []interface{}{}) fake.writePluginConfigMutex.Unlock() - if fake.WritePluginConfigStub != nil { - return fake.WritePluginConfigStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.writePluginConfigReturns return fakeReturns.result1 } @@ -3897,6 +4036,8 @@ func (fake *FakeConfig) Invocations() map[string][][]interface{} { defer fake.cFPasswordMutex.RUnlock() fake.cFUsernameMutex.RLock() defer fake.cFUsernameMutex.RUnlock() + fake.cNBCredentialsMutex.RLock() + defer fake.cNBCredentialsMutex.RUnlock() fake.colorEnabledMutex.RLock() defer fake.colorEnabledMutex.RUnlock() fake.currentUserMutex.RLock() diff --git a/command/config.go b/command/config.go index 44b30e5ba99..676223c7923 100644 --- a/command/config.go +++ b/command/config.go @@ -24,6 +24,7 @@ type Config interface { CurrentUserName() (string, error) DialTimeout() time.Duration DockerPassword() string + CNBCredentials() (map[string]interface{}, error) Experimental() bool GetPlugin(pluginName string) (configv3.Plugin, bool) GetPluginCaseInsensitive(pluginName string) (configv3.Plugin, bool) diff --git a/command/v7/create_app_command.go b/command/v7/create_app_command.go index 938be0bcf73..a4e034cd6db 100644 --- a/command/v7/create_app_command.go +++ b/command/v7/create_app_command.go @@ -1,8 +1,13 @@ package v7 import ( + "errors" + "fmt" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/command" "code.cloudfoundry.org/cli/command/flag" "code.cloudfoundry.org/cli/resources" ) @@ -11,8 +16,9 @@ type CreateAppCommand struct { BaseCommand RequiredArgs flag.AppName `positional-args:"yes"` - AppType flag.AppType `long:"app-type" choice:"buildpack" choice:"docker" description:"App lifecycle type to stage and run the app" default:"buildpack"` - usage interface{} `usage:"CF_NAME create-app APP_NAME [--app-type (buildpack | docker)]"` + AppType flag.AppType `long:"app-type" choice:"buildpack" choice:"docker" choice:"cnb" description:"App lifecycle type to stage and run the app" default:"buildpack"` + Buildpacks []string `long:"buildpack" short:"b" description:"Custom buildpack by name (e.g. my-buildpack), Docker image (e.g. docker://registry/image:tag), Git URL (e.g. 'https://github.com/cloudfoundry/java-buildpack.git') or Git URL with a branch or tag (e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag). To use built-in buildpacks only, specify 'default' or 'null'"` + usage interface{} `usage:"CF_NAME create-app APP_NAME [--app-type (buildpack | docker | cnb)]"` relatedCommands interface{} `related_commands:"app, apps, push"` } @@ -34,11 +40,34 @@ func (cmd CreateAppCommand) Execute(args []string) error { "CurrentUser": user.Name, }) + cmd.UI.DisplayText(fmt.Sprintf("Using app type %q", constant.AppLifecycleType(cmd.AppType))) + + app := resources.Application{ + Name: cmd.RequiredArgs.AppName, + LifecycleType: constant.AppLifecycleType(cmd.AppType), + LifecycleBuildpacks: cmd.Buildpacks, + } + + if constant.AppLifecycleType(cmd.AppType) == constant.AppLifecycleTypeCNB { + err := command.MinimumCCAPIVersionCheck(cmd.Config.APIVersion(), ccversion.MinVersionCNB) + if err != nil { + return err + } + + if len(cmd.Buildpacks) == 0 { + return errors.New("buildpack(s) must be provided when using --app-type cnb") + } + + creds, err := cmd.Config.CNBCredentials() + if err != nil { + return err + } + + app.Credentials = creds + } + _, warnings, err := cmd.Actor.CreateApplicationInSpace( - resources.Application{ - Name: cmd.RequiredArgs.AppName, - LifecycleType: constant.AppLifecycleType(cmd.AppType), - }, + app, cmd.Config.TargetedSpace().GUID, ) cmd.UI.DisplayWarnings(warnings) diff --git a/command/v7/create_app_command_test.go b/command/v7/create_app_command_test.go index 5125dd09b44..dfd39f099aa 100644 --- a/command/v7/create_app_command_test.go +++ b/command/v7/create_app_command_test.go @@ -8,6 +8,7 @@ import ( "code.cloudfoundry.org/cli/actor/v7action" "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/command/commandfakes" "code.cloudfoundry.org/cli/command/flag" v7 "code.cloudfoundry.org/cli/command/v7" @@ -124,6 +125,33 @@ var _ = Describe("create-app Command", func() { Expect(createSpaceGUID).To(Equal("some-space-guid")) }) }) + + When("app type is cnb", func() { + BeforeEach(func() { + cmd.AppType = "cnb" + cmd.Buildpacks = []string{"foo"} + fakeConfig.CNBCredentialsReturns(map[string]interface{}{ + "foo": "bar", + }, nil) + fakeConfig.APIVersionReturns(ccversion.MinVersionCNB) + }) + + It("creates an app with app type: cnb", func() { + Expect(executeErr).ToNot(HaveOccurred()) + + Expect(fakeActor.CreateApplicationInSpaceCallCount()).To(Equal(1)) + createApp, createSpaceGUID := fakeActor.CreateApplicationInSpaceArgsForCall(0) + Expect(createApp).To(Equal(resources.Application{ + Name: app, + LifecycleType: constant.AppLifecycleTypeCNB, + LifecycleBuildpacks: []string{"foo"}, + Credentials: map[string]interface{}{ + "foo": "bar", + }, + })) + Expect(createSpaceGUID).To(Equal("some-space-guid")) + }) + }) }) When("the create is unsuccessful", func() { @@ -168,6 +196,19 @@ var _ = Describe("create-app Command", func() { Expect(testUI.Err).To(Say("I am also a warning")) }) }) + + Context("due to missing buildpacks when AppType is cnb", func() { + BeforeEach(func() { + cmd.AppType = "cnb" + fakeConfig.APIVersionReturns(ccversion.MinVersionCNB) + }) + + It("displays the header and error", func() { + Expect(executeErr).To(MatchError("buildpack(s) must be provided when using --app-type cnb")) + + Expect(testUI.Out).To(Say("Creating app some-app in org some-org / space some-space as banana...")) + }) + }) }) }) }) diff --git a/command/v7/push_command.go b/command/v7/push_command.go index cbf71d78e78..af604ceadbf 100644 --- a/command/v7/push_command.go +++ b/command/v7/push_command.go @@ -16,6 +16,7 @@ import ( "code.cloudfoundry.org/cli/actor/v7pushaction" "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/api/logcache" "code.cloudfoundry.org/cli/cf/errors" "code.cloudfoundry.org/cli/command" @@ -105,8 +106,9 @@ type PushCommand struct { Task bool `long:"task" description:"Push an app that is used only to execute tasks. The app will be staged, but not started and will have no route assigned."` Vars []template.VarKV `long:"var" description:"Variable key value pair for variable substitution, (e.g., name=app1); can specify multiple times"` PathsToVarsFiles []flag.PathWithExistenceCheck `long:"vars-file" description:"Path to a variable substitution file for manifest; can specify multiple times"` + Lifecycle constant.AppLifecycleType `long:"lifecycle" description:"App lifecycle type to stage and run the app" default:""` dockerPassword interface{} `environmentName:"CF_DOCKER_PASSWORD" environmentDescription:"Password used for private docker repository"` - usage interface{} `usage:"CF_NAME push APP_NAME [-b BUILDPACK_NAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]...\n \n CF_NAME push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route ]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]..."` + usage interface{} `usage:"CF_NAME push APP_NAME [-b BUILDPACK_NAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--lifecycle (buildpack | docker | cnb)] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]...\n \n CF_NAME push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route ]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]..."` envCFStagingTimeout interface{} `environmentName:"CF_STAGING_TIMEOUT" environmentDescription:"Max wait time for staging, in minutes" environmentDefault:"15"` envCFStartupTimeout interface{} `environmentName:"CF_STARTUP_TIMEOUT" environmentDescription:"Max wait time for app instance startup, in minutes" environmentDefault:"5"` @@ -164,6 +166,11 @@ func (cmd PushCommand) Execute(args []string) error { return err } + err = command.MinimumCCAPIVersionCheck(cmd.Config.APIVersion(), ccversion.MinVersionCNB) + if flagOverrides.Lifecycle != "" && err != nil { + return err + } + err = cmd.ValidateFlags() if err != nil { return err @@ -174,6 +181,11 @@ func (cmd PushCommand) Execute(args []string) error { return err } + flagOverrides.CNBCredentials, err = cmd.Config.CNBCredentials() + if err != nil { + return err + } + transformedManifest, err := cmd.PushActor.HandleFlagOverrides(baseManifest, flagOverrides) if err != nil { return err @@ -238,6 +250,7 @@ func (cmd PushCommand) Execute(args []string) error { transformedManifest, flagOverrides, ) + cmd.UI.DisplayWarnings(warnings) if err != nil { return err @@ -363,11 +376,70 @@ func (cmd PushCommand) GetFlagOverrides() (v7pushaction.FlagOverrides, error) { NoManifest: cmd.NoManifest, Task: cmd.Task, LogRateLimit: cmd.LogRateLimit, + Lifecycle: cmd.Lifecycle, }, nil } func (cmd PushCommand) ValidateFlags() error { switch { + // Lifecycle buildpack requested + case cmd.Lifecycle == constant.AppLifecycleTypeBuildpack && cmd.DockerImage.Path != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-image, -o", + }, + } + + case cmd.Lifecycle == constant.AppLifecycleTypeBuildpack && cmd.DockerUsername != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-username", + }, + } + + // Lifecycle docker requested + case cmd.Lifecycle == constant.AppLifecycleTypeDocker && cmd.Buildpacks != nil: + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--buildpack, -b", + }, + } + + case cmd.Lifecycle == constant.AppLifecycleTypeDocker && cmd.Stack != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--stack, -s", + }, + } + case cmd.Lifecycle == constant.AppLifecycleTypeDocker && cmd.DropletPath != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--droplet", + }, + } + + // Lifecycle cnb requested + case cmd.Lifecycle == constant.AppLifecycleTypeCNB && cmd.DockerImage.Path != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-image, -o", + }, + } + + case cmd.Lifecycle == constant.AppLifecycleTypeCNB && cmd.DockerUsername != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-username", + }, + } + case cmd.DockerUsername != "" && cmd.DockerImage.Path == "": return translatableerror.RequiredFlagsError{ Arg1: "--docker-image, -o", diff --git a/command/v7/push_command_test.go b/command/v7/push_command_test.go index ead21520928..1a58b4cfafe 100644 --- a/command/v7/push_command_test.go +++ b/command/v7/push_command_test.go @@ -1081,6 +1081,7 @@ var _ = Describe("push Command", func() { cmd.Vars = []template.VarKV{{Name: "key", Value: "val"}} cmd.Task = true cmd.LogRateLimit = "512M" + cmd.Lifecycle = constant.AppLifecycleTypeBuildpack }) JustBeforeEach(func() { @@ -1111,6 +1112,7 @@ var _ = Describe("push Command", func() { Expect(overrides.Task).To(BeTrue()) Expect(overrides.LogRateLimit).To(Equal("512M")) Expect(*overrides.MaxInFlight).To(Equal(1)) + Expect(overrides.Lifecycle).To(BeEquivalentTo("buildpack")) }) When("a docker image is provided", func() { @@ -1313,5 +1315,89 @@ var _ = Describe("push Command", func() { translatableerror.IncorrectUsageError{ Message: "--max-in-flight must be greater than or equal to 1", }), + + Entry("lifecycle buildpack and docker-image flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeBuildpack + cmd.DockerImage = flag.DockerImage{Path: "foo"} + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-image, -o", + }, + }), + + Entry("lifecycle buildpack and docker-username flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeBuildpack + cmd.DockerUsername = "user" + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-username", + }, + }), + + Entry("lifecycle docker and buildpacks flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeDocker + cmd.Buildpacks = []string{"nodejs"} + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--buildpack, -b", + }, + }), + + Entry("lifecycle docker and stck flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeDocker + cmd.Stack = "stack" + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--stack, -s", + }, + }), + + Entry("lifecycle docker and droplet flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeDocker + cmd.DropletPath = flag.PathWithExistenceCheck("path") + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--droplet", + }, + }), + + Entry("lifecycle cnb and docker-image flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeCNB + cmd.DockerImage = flag.DockerImage{Path: "foo"} + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-image, -o", + }, + }), + + Entry("lifecycle cnb and docker-username flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeCNB + cmd.DockerUsername = "user" + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-username", + }, + }), ) }) diff --git a/command/v7/shared/app_summary_displayer.go b/command/v7/shared/app_summary_displayer.go index 46f7e84de2c..60a587f7252 100644 --- a/command/v7/shared/app_summary_displayer.go +++ b/command/v7/shared/app_summary_displayer.go @@ -33,33 +33,24 @@ func (display AppSummaryDisplayer) AppDisplay(summary v7action.DetailedApplicati isoRow = append(isoRow, display.UI.TranslateText("isolation segment:"), name) } + keyValueTable = [][]string{ + {display.UI.TranslateText("name:"), summary.Application.Name}, + {display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))}, + isoRow, + {display.UI.TranslateText("routes:"), routeSummary(summary.Routes)}, + {display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)}, + {display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack}, + } + if summary.LifecycleType == constant.AppLifecycleTypeDocker { - keyValueTable = [][]string{ - {display.UI.TranslateText("name:"), summary.Application.Name}, - {display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))}, - isoRow, - {display.UI.TranslateText("routes:"), routeSummary(summary.Routes)}, - {display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)}, - {display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack}, - {display.UI.TranslateText("docker image:"), summary.CurrentDroplet.Image}, - isoRow, - } + keyValueTable = append(keyValueTable, []string{display.UI.TranslateText("docker image:"), summary.CurrentDroplet.Image}, isoRow) } else { - keyValueTable = [][]string{ - {display.UI.TranslateText("name:"), summary.Application.Name}, - {display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))}, - isoRow, - {display.UI.TranslateText("routes:"), routeSummary(summary.Routes)}, - {display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)}, - {display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack}, - {display.UI.TranslateText("buildpacks:"), ""}, - isoRow, - } + keyValueTable = append(keyValueTable, []string{display.UI.TranslateText("buildpacks:"), ""}, isoRow) } display.UI.DisplayKeyValueTable("", keyValueTable, ui.DefaultTableSpacePadding) - if summary.LifecycleType == constant.AppLifecycleTypeBuildpack { + if summary.LifecycleType != constant.AppLifecycleTypeDocker { display.displayBuildpackTable(summary.CurrentDroplet.Buildpacks) } diff --git a/command/v7/shared/manifest_diff_displayer.go b/command/v7/shared/manifest_diff_displayer.go index 375e000e0a6..254a2c9455b 100644 --- a/command/v7/shared/manifest_diff_displayer.go +++ b/command/v7/shared/manifest_diff_displayer.go @@ -183,10 +183,20 @@ func redactDiff(diff resources.Diff) resources.Diff { return diff } +func redactCNBCredentials(diff resources.Diff) resources.Diff { + if strings.HasSuffix(diff.Path, "cnb-credentials") { + diff.Value = "[PRIVATE DATA HIDDEN]" + } + + return diff +} + func (display *ManifestDiffDisplayer) formatDiff(field string, diff resources.Diff, depth int, addHyphen bool) { if display.RedactEnv { diff = redactDiff(diff) } + + diff = redactCNBCredentials(diff) addHyphen = isInt(field) || addHyphen switch diff.Op { case resources.AddOperation: diff --git a/command/v7/shared/manifest_diff_displayer_test.go b/command/v7/shared/manifest_diff_displayer_test.go index e40dfa2fb4e..e3f63f77e39 100644 --- a/command/v7/shared/manifest_diff_displayer_test.go +++ b/command/v7/shared/manifest_diff_displayer_test.go @@ -572,6 +572,38 @@ applications: }) }) + When("adding cnb-credentials", func() { + BeforeEach(func() { + rawManifest = []byte(`--- +applications: +- name: dora + lifecycle: cnb + cnb-credentials: + foo: bar`) + diff = resources.ManifestDiff{ + Diffs: []resources.Diff{ + { + Op: resources.AddOperation, + Path: "/applications/0/cnb-credentials", + Value: []map[string]interface{}{ + { + "foo": "Bar", + }, + }, + }, + }, + } + }) + + It("redacts output", func() { + Expect(testUI.Out).To(Say(` --- + applications: + - name: dora + lifecycle: cnb +\+ cnb-credentials: '\[PRIVATE DATA HIDDEN\]'`)) + }) + }) + When("remove", func() { BeforeEach(func() { rawManifest = []byte(`--- diff --git a/integration/assets/js-hello/index.js b/integration/assets/js-hello/index.js new file mode 100644 index 00000000000..ed10e718435 --- /dev/null +++ b/integration/assets/js-hello/index.js @@ -0,0 +1,12 @@ +const http = require('http'); + +const server = http.createServer((_req, res) => { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('Hello World\n'); +}); + +const port = process.env.PORT; +server.listen(port, "0.0.0.0", () => { + console.log(`Server running at http://0.0.0.0:${port}/`); +}); diff --git a/integration/assets/js-hello/package.json b/integration/assets/js-hello/package.json new file mode 100644 index 00000000000..5d4ef7f9cff --- /dev/null +++ b/integration/assets/js-hello/package.json @@ -0,0 +1,8 @@ +{ + "name": "js-hello", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "start": "node ./index.js" + } +} diff --git a/integration/helpers/app.go b/integration/helpers/app.go index 1943ddbacc8..f2cd7458ead 100644 --- a/integration/helpers/app.go +++ b/integration/helpers/app.go @@ -129,6 +129,11 @@ func WithMultiBuildpackApp(f func(dir string)) { f("../../assets/go_calls_ruby") } +// WithJSHelloWorld creates a simple JS Hello World HTTP application to use with the CF push command. +func WithJSHelloWorld(f func(dir string)) { + f("../../assets/js-hello") +} + // WithProcfileApp creates an application to use with your CLI command // that contains Procfile defining web and worker processes. func WithProcfileApp(f func(dir string)) { diff --git a/integration/helpers/commonisolated/common_isolated_setup.go b/integration/helpers/commonisolated/common_isolated_setup.go index 17b62c11bda..6fab7989afc 100644 --- a/integration/helpers/commonisolated/common_isolated_setup.go +++ b/integration/helpers/commonisolated/common_isolated_setup.go @@ -41,6 +41,7 @@ func CommonGinkgoSetup( helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") if helpers.IsVersionMet(ccversion.MinVersionHTTP2RoutingV3) { helpers.EnableFeatureFlag("route_sharing") diff --git a/integration/shared/experimental/experimental_suite_test.go b/integration/shared/experimental/experimental_suite_test.go index 4e819c02d36..4861802bf13 100644 --- a/integration/shared/experimental/experimental_suite_test.go +++ b/integration/shared/experimental/experimental_suite_test.go @@ -36,6 +36,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/shared/global/global_suite_test.go b/integration/shared/global/global_suite_test.go index d049a732d40..11288dbdbfc 100644 --- a/integration/shared/global/global_suite_test.go +++ b/integration/shared/global/global_suite_test.go @@ -39,6 +39,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/v7/global/global_suite_test.go b/integration/v7/global/global_suite_test.go index d049a732d40..11288dbdbfc 100644 --- a/integration/v7/global/global_suite_test.go +++ b/integration/v7/global/global_suite_test.go @@ -39,6 +39,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/v7/isolated/app_command_test.go b/integration/v7/isolated/app_command_test.go index e6148783688..967ea83179b 100644 --- a/integration/v7/isolated/app_command_test.go +++ b/integration/v7/isolated/app_command_test.go @@ -6,6 +6,7 @@ import ( "path" "path/filepath" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" . "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers" "code.cloudfoundry.org/cli/integration/helpers" . "github.com/onsi/ginkgo/v2" @@ -407,6 +408,21 @@ applications: }) }) + When("the app is a CNB app", func() { + BeforeEach(func() { + helpers.SkipIfVersionLessThan(ccversion.MinVersionCNB) + helpers.WithJSHelloWorld(func(appDir string) { + Eventually(helpers.CF("push", appName, "-p", appDir, "--lifecycle", "cnb", "-b", "docker://gcr.io/paketo-buildpacks/nodejs:latest")).Should(Exit()) + }) + }) + + It("displays the app buildpacks", func() { + session := helpers.CF("app", appName) + Eventually(session).Should(Say(`paketo-buildpacks\/nodejs`)) + Eventually(session).Should(Exit(0)) + }) + }) + When("the app has tcp routes", func() { var tcpDomain helpers.Domain diff --git a/integration/v7/isolated/create_app_command_test.go b/integration/v7/isolated/create_app_command_test.go index e10dc1872ea..1bd6afdfcc3 100644 --- a/integration/v7/isolated/create_app_command_test.go +++ b/integration/v7/isolated/create_app_command_test.go @@ -1,6 +1,7 @@ package isolated import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" . "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers" "code.cloudfoundry.org/cli/integration/helpers" . "github.com/onsi/ginkgo/v2" @@ -59,7 +60,7 @@ var _ = Describe("create-app command", func() { It("tells the user that the app type is incorrect, prints help text, and exits 1", func() { session := helpers.CF("create-app", appName, "--app-type", "unknown-app-type") - Eventually(session.Err).Should(Say("Incorrect Usage: Invalid value `unknown-app-type' for option `--app-type'. Allowed values are: buildpack or docker")) + Eventually(session.Err).Should(Say("Incorrect Usage: Invalid value `unknown-app-type' for option `--app-type'. Allowed values are: buildpack, docker or cnb")) Eventually(session).Should(Say("NAME:")) Eventually(session).Should(Exit(1)) }) @@ -105,6 +106,19 @@ var _ = Describe("create-app command", func() { Eventually(session).Should(Say("docker image:")) Eventually(session).Should(Exit(0)) }) + + It("creates the app with the cnb app type", func() { + helpers.SkipIfVersionLessThan(ccversion.MinVersionCNB) + session := helpers.CF("create-app", appName, "--app-type", "cnb", "-b", "docker://foobar.test") + userName, _ := helpers.GetCredentials() + Eventually(session).Should(Say("Creating app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName)) + Eventually(session).Should(Say("OK")) + Eventually(session).Should(Exit(0)) + + session = helpers.CF("app", appName) + Eventually(session).ShouldNot(Say("docker image:")) + Eventually(session).Should(Exit(0)) + }) }) }) diff --git a/integration/v7/push/help_test.go b/integration/v7/push/help_test.go index 32845920753..7503e313a38 100644 --- a/integration/v7/push/help_test.go +++ b/integration/v7/push/help_test.go @@ -26,6 +26,7 @@ var _ = Describe("help", func() { "[-b BUILDPACK_NAME]", "[-c COMMAND]", "[-f MANIFEST_PATH | --no-manifest]", + "[--lifecycle (buildpack | docker | cnb)]", "[--no-start]", "[--no-wait]", "[-i NUM_INSTANCES]", diff --git a/integration/v7/push/push_suite_test.go b/integration/v7/push/push_suite_test.go index ebd30ce219f..42423eab717 100644 --- a/integration/v7/push/push_suite_test.go +++ b/integration/v7/push/push_suite_test.go @@ -40,6 +40,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/v7/push/tasks_test.go b/integration/v7/push/tasks_test.go index 4b85976ea2a..319c936eeab 100644 --- a/integration/v7/push/tasks_test.go +++ b/integration/v7/push/tasks_test.go @@ -7,7 +7,6 @@ import ( . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" - . "github.com/onsi/gomega/gexec" ) var _ = Describe("push with --task", func() { @@ -19,7 +18,7 @@ var _ = Describe("push with --task", func() { appName = helpers.NewAppName() helpers.WithHelloWorldApp(func(dir string) { session := helpers.CF("push", appName, "-p", dir, "--task") - Eventually(session).Should(Exit(0)) + Eventually(session).Should(gexec.Exit(0)) }) }) @@ -28,7 +27,7 @@ var _ = Describe("push with --task", func() { BeforeEach(func() { session = helpers.CF("app", appName) - Eventually(session).Should(Exit(0)) + Eventually(session).Should(gexec.Exit(0)) }) It("pushes the app without starting it", func() { diff --git a/resources/application_resource.go b/resources/application_resource.go index b7b5c782557..b9794bb81f9 100644 --- a/resources/application_resource.go +++ b/resources/application_resource.go @@ -25,6 +25,8 @@ type Application struct { SpaceGUID string // State is the desired state of the application. State constant.ApplicationState + // Credentials are used by Cloud Native Buildpacks lifecycle to pull buildpacks + Credentials map[string]interface{} } // ApplicationNameOnly represents only the name field of a Cloud Controller V3 Application @@ -48,7 +50,7 @@ func (a Application) MarshalJSON() ([]byte, error) { if a.LifecycleType == constant.AppLifecycleTypeDocker { ccApp.setDockerLifecycle() - } else if a.LifecycleType == constant.AppLifecycleTypeBuildpack { + } else if a.LifecycleType == constant.AppLifecycleTypeBuildpack || a.LifecycleType == constant.AppLifecycleTypeCNB { if len(a.LifecycleBuildpacks) > 0 || a.StackName != "" { if a.hasAutodetectedBuildpack() { ccApp.setAutodetectedBuildpackLifecycle(a) @@ -100,11 +102,18 @@ func (a Application) hasAutodetectedBuildpack() bool { return a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueDefault || a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueNull } +type ccCredentials map[string]interface{} + +func (ccCredentials) UnmarshalJSON(data []byte) error { + return nil +} + type ccLifecycle struct { Type constant.AppLifecycleType `json:"type,omitempty"` Data struct { - Buildpacks []string `json:"buildpacks,omitempty"` - Stack string `json:"stack,omitempty"` + Buildpacks []string `json:"buildpacks,omitempty"` + Stack string `json:"stack,omitempty"` + Credentials ccCredentials `json:"credentials,omitempty"` } `json:"data"` } @@ -135,6 +144,7 @@ func (ccApp *ccApplication) setBuildpackLifecycle(a Application) { lifecycle.Type = a.LifecycleType lifecycle.Data.Buildpacks = a.LifecycleBuildpacks lifecycle.Data.Stack = a.StackName + lifecycle.Data.Credentials = a.Credentials ccApp.Lifecycle = lifecycle } diff --git a/util/configv3/env.go b/util/configv3/env.go index efd935e37d0..27e15504fcd 100644 --- a/util/configv3/env.go +++ b/util/configv3/env.go @@ -1,6 +1,7 @@ package configv3 import ( + "encoding/json" "strconv" "strings" "time" @@ -20,6 +21,7 @@ type EnvOverride struct { CFTrace string CFUsername string DockerPassword string + CNBCredentials string Experimental string ForceTTY string HTTPSProxy string @@ -61,6 +63,21 @@ func (config *Config) DockerPassword() string { return config.ENV.DockerPassword } +// CNBCredentials retrurns CNB credentials from the environment +func (config *Config) CNBCredentials() (map[string]interface{}, error) { + if config.ENV.CNBCredentials == "" { + return nil, nil + } + + creds := map[string]interface{}{} + + if err := json.Unmarshal([]byte(config.ENV.CNBCredentials), &creds); err != nil { + return nil, err + } + + return creds, nil +} + // Experimental returns whether or not to run experimental CLI commands. This // is based on the following: // 1. The $CF_CLI_EXPERIMENTAL environment variable if set diff --git a/util/configv3/load_config.go b/util/configv3/load_config.go index c57b84510fc..d0a0c8b5026 100644 --- a/util/configv3/load_config.go +++ b/util/configv3/load_config.go @@ -128,6 +128,7 @@ func LoadConfig(flags ...FlagOverride) (*Config, error) { CFTrace: os.Getenv("CF_TRACE"), CFUsername: os.Getenv("CF_USERNAME"), DockerPassword: os.Getenv("CF_DOCKER_PASSWORD"), + CNBCredentials: os.Getenv("CF_CNB_REGISTRY_CREDS"), Experimental: os.Getenv("CF_CLI_EXPERIMENTAL"), ForceTTY: os.Getenv("FORCE_TTY"), HTTPSProxy: os.Getenv("https_proxy"), diff --git a/util/manifestparser/application.go b/util/manifestparser/application.go index 3b12942dfcc..2ce7d936701 100644 --- a/util/manifestparser/application.go +++ b/util/manifestparser/application.go @@ -16,22 +16,23 @@ type Docker struct { // add a field for the CLI to extract from the manifest, just add it to this // struct. type Application struct { - Name string `yaml:"name"` - DiskQuota string `yaml:"disk-quota,omitempty"` - Docker *Docker `yaml:"docker,omitempty"` - HealthCheckType constant.HealthCheckType `yaml:"health-check-type,omitempty"` - HealthCheckEndpoint string `yaml:"health-check-http-endpoint,omitempty"` - HealthCheckTimeout int64 `yaml:"timeout,omitempty"` - Instances *int `yaml:"instances,omitempty"` - Path string `yaml:"path,omitempty"` - Processes []Process `yaml:"processes,omitempty"` - Memory string `yaml:"memory,omitempty"` - NoRoute bool `yaml:"no-route,omitempty"` - RandomRoute bool `yaml:"random-route,omitempty"` - DefaultRoute bool `yaml:"default-route,omitempty"` - Stack string `yaml:"stack,omitempty"` - LogRateLimit string `yaml:"log-rate-limit-per-second,omitempty"` - RemainingManifestFields map[string]interface{} `yaml:"-,inline"` + Name string `yaml:"name"` + DiskQuota string `yaml:"disk-quota,omitempty"` + Docker *Docker `yaml:"docker,omitempty"` + HealthCheckType constant.HealthCheckType `yaml:"health-check-type,omitempty"` + HealthCheckEndpoint string `yaml:"health-check-http-endpoint,omitempty"` + HealthCheckTimeout int64 `yaml:"timeout,omitempty"` + Instances *int `yaml:"instances,omitempty"` + Path string `yaml:"path,omitempty"` + Processes []Process `yaml:"processes,omitempty"` + Memory string `yaml:"memory,omitempty"` + NoRoute bool `yaml:"no-route,omitempty"` + RandomRoute bool `yaml:"random-route,omitempty"` + DefaultRoute bool `yaml:"default-route,omitempty"` + Stack string `yaml:"stack,omitempty"` + LogRateLimit string `yaml:"log-rate-limit-per-second,omitempty"` + Lifecycle constant.AppLifecycleType `yaml:"lifecycle,omitempty"` + RemainingManifestFields map[string]interface{} `yaml:"-,inline"` } func (application Application) HasBuildpacks() bool { From c867dd8a163d52c1189c3d3ac20e5bbe5947538a Mon Sep 17 00:00:00 2001 From: Ralf Pannemans Date: Mon, 18 Nov 2024 16:14:11 +0100 Subject: [PATCH 14/21] Rearrange subcommands to be in alphabetical order again (#3298) --- command/v7/push_command.go | 1 + 1 file changed, 1 insertion(+) diff --git a/command/v7/push_command.go b/command/v7/push_command.go index af604ceadbf..eafb011f239 100644 --- a/command/v7/push_command.go +++ b/command/v7/push_command.go @@ -89,6 +89,7 @@ type PushCommand struct { HealthCheckHTTPEndpoint string `long:"endpoint" description:"Valid path on the app for an HTTP health check. Only used when specifying --health-check-type=http"` HealthCheckType flag.HealthCheckType `long:"health-check-type" short:"u" description:"Application health check type. Defaults to 'port'. 'http' requires a valid endpoint, for example, '/health'."` Instances flag.Instances `long:"instances" short:"i" description:"Number of instances"` + Lifecycle constant.AppLifecycleType `long:"lifecycle" description:"App lifecycle type to stage and run the app" default:""` LogRateLimit string `long:"log-rate-limit" short:"l" description:"Log rate limit per second, in bytes (e.g. 128B, 4K, 1M). -l=-1 represents unlimited"` PathToManifest flag.ManifestPathWithExistenceCheck `long:"manifest" short:"f" description:"Path to manifest"` MaxInFlight *int `long:"max-in-flight" description:"Defines the maximum number of instances that will be actively being started. Only applies when --strategy flag is specified."` From 711446d04e71353f0bdcaf76dc342bfd058e104d Mon Sep 17 00:00:00 2001 From: Shwetha Gururaj Date: Mon, 18 Nov 2024 11:11:18 -0500 Subject: [PATCH 15/21] Add nonbase64 sha256 support [v8] (#3307) * Add sha256 support * Add negative test --- util/clissh/ssh.go | 13 ++++++++++--- util/clissh/ssh_test.go | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/util/clissh/ssh.go b/util/clissh/ssh.go index a6f32ce7115..b4f29212428 100644 --- a/util/clissh/ssh.go +++ b/util/clissh/ssh.go @@ -5,6 +5,7 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/base64" + "encoding/hex" "errors" "fmt" "io" @@ -28,6 +29,7 @@ const ( md5FingerprintLength = 47 // inclusive of space between bytes hexSha1FingerprintLength = 59 // inclusive of space between bytes base64Sha256FingerprintLength = 43 + sha256FingerprintLength = 64 DefaultKeepAliveInterval = 30 * time.Second ) @@ -331,9 +333,12 @@ func (c *SecureShell) terminalType() string { return term } -func base64Sha256Fingerprint(key ssh.PublicKey) string { +func sha256Fingerprint(key ssh.PublicKey, encode bool) string { sum := sha256.Sum256(key.Marshal()) - return base64.RawStdEncoding.EncodeToString(sum[:]) + if encode { + return base64.RawStdEncoding.EncodeToString(sum[:]) + } + return hex.EncodeToString(sum[:]) } func copyAndClose(wg *sync.WaitGroup, dest io.WriteCloser, src io.Reader) { @@ -364,8 +369,10 @@ func fingerprintCallback(skipHostValidation bool, expectedFingerprint string) ss var fingerprint string switch len(expectedFingerprint) { + case sha256FingerprintLength: + fingerprint = sha256Fingerprint(key, false) case base64Sha256FingerprintLength: - fingerprint = base64Sha256Fingerprint(key) + fingerprint = sha256Fingerprint(key, true) case hexSha1FingerprintLength: fingerprint = hexSha1Fingerprint(key) case md5FingerprintLength: diff --git a/util/clissh/ssh_test.go b/util/clissh/ssh_test.go index 5b7a2a7c2a9..46a03b32181 100644 --- a/util/clissh/ssh_test.go +++ b/util/clissh/ssh_test.go @@ -253,6 +253,28 @@ var _ = Describe("CLI SSH", Serial, FlakeAttempts(9), func() { }) }) + Context("when the sha256 fingerprint matches", func() { + BeforeEach(func() { + sshEndpointFingerprint = "b29fe3acbba3ebaafecab2c350a65d254e6d773b789aafd469288d063a60afef" + }) + + It("does not return an error", func() { + Expect(callback("", addr, TestHostKey.PublicKey())).ToNot(HaveOccurred()) + }) + }) + + When("the SHA256 fingerprint does not match", func() { + BeforeEach(func() { + sshEndpointFingerprint = "0000000000000000000000000000000000000000000000000000000000000000" + }) + + It("returns an error'", func() { + err := callback("", addr, TestHostKey.PublicKey()) + Expect(err).To(MatchError(MatchRegexp(`Host key verification failed\.`))) + Expect(err).To(MatchError(MatchRegexp("The fingerprint of the received key was \".*\""))) + }) + }) + When("the base64 SHA256 fingerprint does not match", func() { BeforeEach(func() { sshEndpointFingerprint = "0000000000000000000000000000000000000000000" From 608920ee6e900285661fecd39f8dff4896e1cbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pereira?= Date: Wed, 20 Nov 2024 00:59:59 -0600 Subject: [PATCH 16/21] Fix linter for v8 (#3311) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - remove duplicate Lifecycle command Signed-off-by: João Pereira --- command/v7/push_command.go | 1 - 1 file changed, 1 deletion(-) diff --git a/command/v7/push_command.go b/command/v7/push_command.go index eafb011f239..717e373b560 100644 --- a/command/v7/push_command.go +++ b/command/v7/push_command.go @@ -107,7 +107,6 @@ type PushCommand struct { Task bool `long:"task" description:"Push an app that is used only to execute tasks. The app will be staged, but not started and will have no route assigned."` Vars []template.VarKV `long:"var" description:"Variable key value pair for variable substitution, (e.g., name=app1); can specify multiple times"` PathsToVarsFiles []flag.PathWithExistenceCheck `long:"vars-file" description:"Path to a variable substitution file for manifest; can specify multiple times"` - Lifecycle constant.AppLifecycleType `long:"lifecycle" description:"App lifecycle type to stage and run the app" default:""` dockerPassword interface{} `environmentName:"CF_DOCKER_PASSWORD" environmentDescription:"Password used for private docker repository"` usage interface{} `usage:"CF_NAME push APP_NAME [-b BUILDPACK_NAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--lifecycle (buildpack | docker | cnb)] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]...\n \n CF_NAME push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route ]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]..."` envCFStagingTimeout interface{} `environmentName:"CF_STAGING_TIMEOUT" environmentDescription:"Max wait time for staging, in minutes" environmentDefault:"15"` From 29c5df2e8bdec8d5ee6c071fd13fe724e0888846 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 07:13:28 -0800 Subject: [PATCH 17/21] [v8](go): Bump the dependencies group across 1 directory with 4 updates (#3312) Bumps the dependencies group with 4 updates in the / directory: [code.cloudfoundry.org/bytefmt](https://github.com/cloudfoundry/bytefmt), [code.cloudfoundry.org/clock](https://github.com/cloudfoundry/clock), [code.cloudfoundry.org/lager/v3](https://github.com/cloudfoundry/lager) and [code.cloudfoundry.org/tlsconfig](https://github.com/cloudfoundry/tlsconfig). Updates `code.cloudfoundry.org/bytefmt` from 0.17.0 to 0.18.0 - [Release notes](https://github.com/cloudfoundry/bytefmt/releases) - [Commits](https://github.com/cloudfoundry/bytefmt/compare/v0.17.0...v0.18.0) Updates `code.cloudfoundry.org/clock` from 1.20.0 to 1.21.0 - [Release notes](https://github.com/cloudfoundry/clock/releases) - [Commits](https://github.com/cloudfoundry/clock/compare/v1.20.0...v1.21.0) Updates `code.cloudfoundry.org/lager/v3` from 3.14.0 to 3.15.0 - [Release notes](https://github.com/cloudfoundry/lager/releases) - [Commits](https://github.com/cloudfoundry/lager/compare/v3.14.0...v3.15.0) Updates `code.cloudfoundry.org/tlsconfig` from 0.8.0 to 0.10.0 - [Release notes](https://github.com/cloudfoundry/tlsconfig/releases) - [Commits](https://github.com/cloudfoundry/tlsconfig/compare/v0.8.0...v0.10.0) --- updated-dependencies: - dependency-name: code.cloudfoundry.org/bytefmt dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/clock dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/lager/v3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/tlsconfig dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 877798a71c9..397d3b2c00b 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,18 @@ module code.cloudfoundry.org/cli go 1.23.1 require ( - code.cloudfoundry.org/bytefmt v0.17.0 + code.cloudfoundry.org/bytefmt v0.18.0 code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 - code.cloudfoundry.org/clock v1.20.0 + code.cloudfoundry.org/clock v1.21.0 code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 code.cloudfoundry.org/go-log-cache/v2 v2.0.7 code.cloudfoundry.org/go-loggregator/v9 v9.2.1 code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f code.cloudfoundry.org/jsonry v1.1.4 - code.cloudfoundry.org/lager/v3 v3.14.0 - code.cloudfoundry.org/tlsconfig v0.8.0 + code.cloudfoundry.org/lager/v3 v3.15.0 + code.cloudfoundry.org/tlsconfig v0.10.0 code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 github.com/blang/semver/v4 v4.0.0 @@ -78,12 +78,12 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect - golang.org/x/mod v0.21.0 // indirect + golang.org/x/mod v0.22.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.27.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect diff --git a/go.sum b/go.sum index 283a76c5487..1473e995dbe 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ -code.cloudfoundry.org/bytefmt v0.17.0 h1:p8lUUWcqRw1gzZp0/McEtoMytE/5f8rPo2AkE9g8Pt0= -code.cloudfoundry.org/bytefmt v0.17.0/go.mod h1:Gep8GOASWFixDTjr+1C8lEqphdvS0djnDGXrlUkDVu8= +code.cloudfoundry.org/bytefmt v0.18.0 h1:bx2J35AAWP4QM7ZGc+yCdQVc15co3O+YpbvMgt7znsI= +code.cloudfoundry.org/bytefmt v0.18.0/go.mod h1:NdqIsywmPwFaEuUArvb9yrBBVjaZBt1onJ8GtElZf6w= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 h1:Yc9r1p21kEpni9WlG4mwOZw87TB2QlyS9sAEebZ3+ak= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6/go.mod h1:u5FovqC5GGAEbFPz+IdjycDA+gIjhUwqxnu0vbHwVeM= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 h1:jaHWw9opYjKPrDT19uydBBWSxl+g5F4Hv030fqMsalo= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85/go.mod h1:R1EiyOAr7lW0l/YkZNqItUNZ01Q/dYUfbTn4X4Z+82M= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 h1:O+j8afQWaDuxzKGcculsjgHGK+biBTn6iMjgFpBf54c= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4/go.mod h1:dVTgo9kQbYns/QM4A1C2GtxqUnFSvJTk2Qhw+M0/uzk= -code.cloudfoundry.org/clock v1.20.0 h1:evna9D0iZm2LGEOTH1qooDdGcsTx4wfACdCArWpBpbU= -code.cloudfoundry.org/clock v1.20.0/go.mod h1:lbTmT6tMYRsX878c49dSgbn0+jO1W2iYPOcOwYyV0Yk= +code.cloudfoundry.org/clock v1.21.0 h1:RFRz2iYx9/UynpK7U97a5u5z91t6mr/izP7+0QGtrJw= +code.cloudfoundry.org/clock v1.21.0/go.mod h1:hgxNVpH5uqC1CeVocIe9TKol+jJ3Estd5SNXPk7kMwQ= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 h1:Bns1y0jSlcvfP0u8ael+TUlnyNHsNX808zuo58bf5so= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82/go.mod h1:L2/glHnSK+wKnsG8oZZqdV2sgYY9NDo/I1aDJGhcWaM= code.cloudfoundry.org/go-log-cache/v2 v2.0.7 h1:yR/JjQ/RscO1n4xVAT9HDYcpx5ET/3Cq2/RhpJml6ZU= @@ -21,10 +21,10 @@ code.cloudfoundry.org/inigo v0.0.0-20230612153013-b300679e6ed6/go.mod h1:1ZB1JCh code.cloudfoundry.org/jsonry v1.1.4 h1:P9N7IlH1/4aRCLcXLgLFj1hkcBmV7muijJzY+K6U4hE= code.cloudfoundry.org/jsonry v1.1.4/go.mod h1:6aKilShQP7w/Ez76h1El2/n9y2OkHuU56nKSBB9Gp0A= code.cloudfoundry.org/lager v1.1.1-0.20191008172124-a9afc05ee5be/go.mod h1:O2sS7gKP3HM2iemG+EnwvyNQK7pTSC6Foi4QiMp9sSk= -code.cloudfoundry.org/lager/v3 v3.14.0 h1:W6W1VhS4df8TvXCVo0lj5ve/hjF6YarmU0hsjA/phg4= -code.cloudfoundry.org/lager/v3 v3.14.0/go.mod h1:beQQaqGk0JSc5Nl/CZFGPCY05lm/wIRa+RoJh7Hz7jI= -code.cloudfoundry.org/tlsconfig v0.8.0 h1:2kg6Y8ix58T+84iDu1yAFEx6wsHfkg5Mah4twdtbeIs= -code.cloudfoundry.org/tlsconfig v0.8.0/go.mod h1:S6L3WxtIy4a4wPnmtqUQXiIYlrIk7tUIXj5z+5QYqGY= +code.cloudfoundry.org/lager/v3 v3.15.0 h1:n31lbeh9krwuQLCRUWNEVZBk/BFEtyhQBwDZxFauPw4= +code.cloudfoundry.org/lager/v3 v3.15.0/go.mod h1:x5XGPsP6QF0HMW/FpRilBHu4gy+cWRur8/fiZEyj6z8= +code.cloudfoundry.org/tlsconfig v0.10.0 h1:IGbLsOfQmzjI1o5bcGtsTwsZl/Qoz/n5/NkBK68Lk1I= +code.cloudfoundry.org/tlsconfig v0.10.0/go.mod h1:Rz8UI6zoOnB9UFxYfPpZhAsl2hDsmjmVW9SGmUhsDSk= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d h1:M+zXqtXJqcsmpL76aU0tdl1ho23eYa4axYoM4gD62UA= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d/go.mod h1:YUJiVOr5xl0N/RjMxM1tHmgSpBbi5UM+KoVR5AoejO0= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -257,8 +257,8 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.step.sm/crypto v0.54.0 h1:V8p+12Ld0NRA/RBMYoKXA0dWmVKZSdCwP56IwzweT9g= -go.step.sm/crypto v0.54.0/go.mod h1:vQJyTngfZDW+UyZdFzOMCY/txWDAmcwViEUC7Gn4YfU= +go.step.sm/crypto v0.54.2 h1:3LSA5nYDQvcd484OSx7xsS3XDqQ7/WZjVqvq0+a0fWc= +go.step.sm/crypto v0.54.2/go.mod h1:1+OjUozd5aA3TkBJfr5Aobd6vNt9F70n1DagcoBh3Pc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -271,8 +271,8 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180418062111-d41e8174641f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -347,8 +347,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From bf7a3ad7fc0a54600319d45bf48af402a0b39930 Mon Sep 17 00:00:00 2001 From: Sam Gunaratne <385176+Samze@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:51:53 -0700 Subject: [PATCH 18/21] Add cf task command (#3320) --- command/common/command_list_v7.go | 1 + command/common/internal/help_all_display.go | 2 +- command/flag/arguments.go | 5 + command/v7/run_task_command.go | 2 +- command/v7/task_command.go | 71 +++++ command/v7/task_command_test.go | 282 ++++++++++++++++++ command/v7/tasks_command.go | 2 +- command/v7/terminate_task_command.go | 2 +- .../v7/isolated/run_task_command_test.go | 2 +- integration/v7/isolated/task_command_test.go | 127 ++++++++ integration/v7/isolated/tasks_command_test.go | 2 +- resources/task_resource.go | 7 + 12 files changed, 499 insertions(+), 6 deletions(-) create mode 100644 command/v7/task_command.go create mode 100644 command/v7/task_command_test.go create mode 100644 integration/v7/isolated/task_command_test.go diff --git a/command/common/command_list_v7.go b/command/common/command_list_v7.go index f752d224aed..bba46d9fa91 100644 --- a/command/common/command_list_v7.go +++ b/command/common/command_list_v7.go @@ -172,6 +172,7 @@ type commandList struct { Start v7.StartCommand `command:"start" alias:"st" description:"Start an app"` Stop v7.StopCommand `command:"stop" alias:"sp" description:"Stop an app"` Target v7.TargetCommand `command:"target" alias:"t" description:"Set or view the targeted org or space"` + Task v7.TaskCommand `command:"task" description:"Display a task of an app"` Tasks v7.TasksCommand `command:"tasks" description:"List tasks of an app"` TerminateTask v7.TerminateTaskCommand `command:"terminate-task" description:"Terminate a running task of an app"` MoveRoute v7.MoveRouteCommand `command:"move-route" description:"Assign a route to a different space"` diff --git a/command/common/internal/help_all_display.go b/command/common/internal/help_all_display.go index 9090f70f46f..b3a8ca198af 100644 --- a/command/common/internal/help_all_display.go +++ b/command/common/internal/help_all_display.go @@ -15,7 +15,7 @@ var HelpCategoryList = []HelpCategory{ {"push", "scale", "delete", "rename"}, {"cancel-deployment", "continue-deployment"}, {"start", "stop", "restart", "stage-package", "restage", "restart-app-instance"}, - {"run-task", "tasks", "terminate-task"}, + {"run-task", "task", "tasks", "terminate-task"}, {"packages", "create-package"}, {"revisions", "rollback"}, {"droplets", "set-droplet", "download-droplet"}, diff --git a/command/flag/arguments.go b/command/flag/arguments.go index 2ede06676f1..9e3d60263f8 100644 --- a/command/flag/arguments.go +++ b/command/flag/arguments.go @@ -408,3 +408,8 @@ type RemoveNetworkPolicyArgsV7 struct { SourceApp string `positional-arg-name:"SOURCE_APP" required:"true" description:"The source app"` DestApp string `positional-arg-name:"DESTINATION_APP" required:"true" description:"The destination app"` } + +type TaskArgs struct { + AppName string `positional-arg-name:"APP_NAME" required:"true" description:"The application name"` + TaskID int `positional-arg-name:"TASK_ID" required:"true" description:"The Task ID for the application"` +} diff --git a/command/v7/run_task_command.go b/command/v7/run_task_command.go index 61defab7818..a8f6e96b153 100644 --- a/command/v7/run_task_command.go +++ b/command/v7/run_task_command.go @@ -19,7 +19,7 @@ type RunTaskCommand struct { Process string `long:"process" description:"Process type to use as a template for command, memory, and disk for the created task."` Wait bool `long:"wait" short:"w" description:"Wait for the task to complete before exiting"` usage interface{} `usage:"CF_NAME run-task APP_NAME [--command COMMAND] [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [--name TASK_NAME] [--process PROCESS_TYPE]\n\nTIP:\n Use 'cf logs' to display the logs of the app and all its tasks. If your task name is unique, grep this command's output for the task name to view task-specific logs.\n\nEXAMPLES:\n CF_NAME run-task my-app --command \"bundle exec rake db:migrate\" --name migrate\n\n CF_NAME run-task my-app --process batch_job\n\n CF_NAME run-task my-app"` - relatedCommands interface{} `related_commands:"logs, tasks, terminate-task"` + relatedCommands interface{} `related_commands:"logs, tasks, task, terminate-task"` } func (cmd RunTaskCommand) Execute(args []string) error { diff --git a/command/v7/task_command.go b/command/v7/task_command.go new file mode 100644 index 00000000000..44fe05ce3d8 --- /dev/null +++ b/command/v7/task_command.go @@ -0,0 +1,71 @@ +package v7 + +import ( + "strconv" + + "code.cloudfoundry.org/cli/command/flag" + "code.cloudfoundry.org/cli/util/ui" +) + +type TaskCommand struct { + BaseCommand + + RequiredArgs flag.TaskArgs `positional-args:"yes"` + usage interface{} `usage:"CF_NAME task APP_NAME TASK_ID"` + relatedCommands interface{} `related_commands:"apps, logs, run-task, tasks, terminate-task"` +} + +func (cmd TaskCommand) Execute(args []string) error { + err := cmd.SharedActor.CheckTarget(true, true) + if err != nil { + return err + } + + space := cmd.Config.TargetedSpace() + + user, err := cmd.Actor.GetCurrentUser() + if err != nil { + return err + } + + application, warnings, err := cmd.Actor.GetApplicationByNameAndSpace(cmd.RequiredArgs.AppName, space.GUID) + cmd.UI.DisplayWarnings(warnings) + if err != nil { + return err + } + + cmd.UI.DisplayTextWithFlavor("Getting task {{.TaskID}} for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...", map[string]interface{}{ + "TaskID": cmd.RequiredArgs.TaskID, + "AppName": cmd.RequiredArgs.AppName, + "OrgName": cmd.Config.TargetedOrganization().Name, + "SpaceName": space.Name, + "CurrentUser": user.Name, + }) + cmd.UI.DisplayNewline() + + task, warnings, err := cmd.Actor.GetTaskBySequenceIDAndApplication(cmd.RequiredArgs.TaskID, application.GUID) + cmd.UI.DisplayWarnings(warnings) + if err != nil { + return err + } + + if task.Command == "" { + task.Command = "[hidden]" + } + + table := [][]string{ + {cmd.UI.TranslateText("id:"), strconv.FormatInt(task.SequenceID, 10)}, + {cmd.UI.TranslateText("name:"), task.Name}, + {cmd.UI.TranslateText("state:"), string(task.State)}, + {cmd.UI.TranslateText("start time:"), task.CreatedAt}, + {cmd.UI.TranslateText("command:"), task.Command}, + {cmd.UI.TranslateText("memory in mb:"), strconv.FormatUint(task.MemoryInMB, 10)}, + {cmd.UI.TranslateText("disk in mb:"), strconv.FormatUint(task.DiskInMB, 10)}, + {cmd.UI.TranslateText("log rate limit:"), strconv.Itoa(task.LogRateLimitInBPS)}, + {cmd.UI.TranslateText("failure reason:"), task.Result.FailureReason}, + } + + cmd.UI.DisplayKeyValueTable("", table, ui.DefaultTableSpacePadding) + + return nil +} diff --git a/command/v7/task_command_test.go b/command/v7/task_command_test.go new file mode 100644 index 00000000000..9d2ccdc3e6c --- /dev/null +++ b/command/v7/task_command_test.go @@ -0,0 +1,282 @@ +package v7_test + +import ( + "errors" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/actor/v7action" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/command/commandfakes" + . "code.cloudfoundry.org/cli/command/v7" + "code.cloudfoundry.org/cli/command/v7/v7fakes" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/configv3" + "code.cloudfoundry.org/cli/util/ui" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gbytes" +) + +var _ = Describe("task Command", func() { + var ( + cmd TaskCommand + testUI *ui.UI + fakeConfig *commandfakes.FakeConfig + fakeSharedActor *commandfakes.FakeSharedActor + fakeActor *v7fakes.FakeActor + binaryName string + executeErr error + ) + + BeforeEach(func() { + testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) + fakeConfig = new(commandfakes.FakeConfig) + fakeSharedActor = new(commandfakes.FakeSharedActor) + fakeActor = new(v7fakes.FakeActor) + + cmd = TaskCommand{ + BaseCommand: BaseCommand{ + UI: testUI, + Config: fakeConfig, + SharedActor: fakeSharedActor, + Actor: fakeActor, + }, + } + + cmd.RequiredArgs.AppName = "some-app-name" + cmd.RequiredArgs.TaskID = 3 + + binaryName = "faceman" + fakeConfig.BinaryNameReturns(binaryName) + }) + + JustBeforeEach(func() { + executeErr = cmd.Execute(nil) + }) + + When("checking target fails", func() { + BeforeEach(func() { + fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName}) + }) + + It("returns an error", func() { + Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName})) + + Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) + checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) + Expect(checkTargetedOrg).To(BeTrue()) + Expect(checkTargetedSpace).To(BeTrue()) + }) + }) + + When("the user is logged in, and a space and org are targeted", func() { + BeforeEach(func() { + fakeConfig.HasTargetedOrganizationReturns(true) + fakeConfig.TargetedOrganizationReturns(configv3.Organization{ + GUID: "some-org-guid", + Name: "some-org", + }) + fakeConfig.HasTargetedSpaceReturns(true) + fakeConfig.TargetedSpaceReturns(configv3.Space{ + GUID: "some-space-guid", + Name: "some-space", + }) + }) + + When("getting the current user returns an error", func() { + var expectedErr error + + BeforeEach(func() { + expectedErr = errors.New("get current user error") + fakeActor.GetCurrentUserReturns( + configv3.User{}, + expectedErr) + }) + + It("returns the error", func() { + Expect(executeErr).To(MatchError(expectedErr)) + }) + }) + + When("getting the current user does not return an error", func() { + BeforeEach(func() { + fakeActor.GetCurrentUserReturns( + configv3.User{Name: "some-user"}, + nil) + }) + + When("provided a valid application name", func() { + BeforeEach(func() { + fakeActor.GetApplicationByNameAndSpaceReturns( + resources.Application{GUID: "some-app-guid"}, + v7action.Warnings{"get-application-warning-1", "get-application-warning-2"}, + nil) + fakeActor.GetTaskBySequenceIDAndApplicationReturns( + resources.Task{ + GUID: "task-3-guid", + SequenceID: 3, + Name: "task-3", + State: constant.TaskRunning, + CreatedAt: "2016-11-08T22:26:02Z", + Command: "some-command", + MemoryInMB: 100, + DiskInMB: 200, + LogRateLimitInBPS: 300, + Result: &resources.TaskResult{ + FailureReason: "some failure message", + }, + }, + v7action.Warnings{"get-task-warning-1"}, + nil) + }) + + It("outputs the task and all warnings", func() { + Expect(executeErr).ToNot(HaveOccurred()) + + Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1)) + appName, spaceGUID := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0) + Expect(appName).To(Equal("some-app-name")) + Expect(spaceGUID).To(Equal("some-space-guid")) + + Expect(fakeActor.GetTaskBySequenceIDAndApplicationCallCount()).To(Equal(1)) + taskId, appGuid := fakeActor.GetTaskBySequenceIDAndApplicationArgsForCall(0) + Expect(taskId).To(Equal(3)) + Expect(appGuid).To(Equal("some-app-guid")) + + Expect(testUI.Out).To(Say("Getting task 3 for app some-app-name in org some-org / space some-space as some-user...")) + + Expect(testUI.Out).To(Say(`id:\s+3`)) + Expect(testUI.Out).To(Say(`name:\s+task-3`)) + Expect(testUI.Out).To(Say(`state:\s+RUNNING`)) + Expect(testUI.Out).To(Say(`start time:\s+2016-11-08T22:26:02Z`)) + Expect(testUI.Out).To(Say(`command:\s+some-command`)) + Expect(testUI.Out).To(Say(`memory in mb:\s+100`)) + Expect(testUI.Out).To(Say(`disk in mb:\s+200`)) + Expect(testUI.Out).To(Say(`log rate limit:\s+300`)) + Expect(testUI.Out).To(Say(`failure reason:\s+some failure message`)) + + Expect(testUI.Err).To(Say("get-application-warning-1")) + Expect(testUI.Err).To(Say("get-application-warning-2")) + Expect(testUI.Err).To(Say("get-task-warning-1")) + }) + + When("the API does not return a command", func() { + BeforeEach(func() { + fakeActor.GetTaskBySequenceIDAndApplicationReturns( + resources.Task{ + GUID: "task-3-guid", + SequenceID: 3, + Name: "task-3", + State: constant.TaskRunning, + CreatedAt: "2016-11-08T22:26:02Z", + Command: "", + MemoryInMB: 100, + DiskInMB: 200, + LogRateLimitInBPS: 300, + Result: &resources.TaskResult{ + FailureReason: "some failure message", + }, + }, + v7action.Warnings{"get-task-warning-1"}, + nil) + }) + It("displays [hidden] for the command", func() { + Expect(executeErr).ToNot(HaveOccurred()) + Expect(testUI.Out).To(Say(`.*command:\s+\[hidden\]`)) + }) + }) + }) + + When("there are errors", func() { + When("the error is translatable", func() { + When("getting the application returns the error", func() { + var ( + returnedErr error + expectedErr error + ) + + BeforeEach(func() { + expectedErr = errors.New("request-error") + returnedErr = ccerror.RequestError{Err: expectedErr} + fakeActor.GetApplicationByNameAndSpaceReturns( + resources.Application{GUID: "some-app-guid"}, + nil, + returnedErr) + }) + + It("returns a translatable error", func() { + Expect(executeErr).To(MatchError(ccerror.RequestError{Err: expectedErr})) + }) + }) + + When("getting the app task returns the error", func() { + var returnedErr error + + BeforeEach(func() { + returnedErr = ccerror.UnverifiedServerError{URL: "some-url"} + fakeActor.GetApplicationByNameAndSpaceReturns( + resources.Application{GUID: "some-app-guid"}, + nil, + nil) + fakeActor.GetTaskBySequenceIDAndApplicationReturns( + resources.Task{}, + nil, + returnedErr) + }) + + It("returns a translatable error", func() { + Expect(executeErr).To(MatchError(returnedErr)) + }) + }) + }) + + When("the error is not translatable", func() { + When("getting the app returns the error", func() { + var expectedErr error + + BeforeEach(func() { + expectedErr = errors.New("bananapants") + fakeActor.GetApplicationByNameAndSpaceReturns( + resources.Application{GUID: "some-app-guid"}, + v7action.Warnings{"get-application-warning-1", "get-application-warning-2"}, + expectedErr) + }) + + It("return the error and outputs all warnings", func() { + Expect(executeErr).To(MatchError(expectedErr)) + + Expect(testUI.Err).To(Say("get-application-warning-1")) + Expect(testUI.Err).To(Say("get-application-warning-2")) + }) + }) + + When("getting the app task returns the error", func() { + var expectedErr error + + BeforeEach(func() { + expectedErr = errors.New("bananapants??") + fakeActor.GetApplicationByNameAndSpaceReturns( + resources.Application{GUID: "some-app-guid"}, + v7action.Warnings{"get-application-warning-1", "get-application-warning-2"}, + nil) + fakeActor.GetTaskBySequenceIDAndApplicationReturns( + resources.Task{}, + v7action.Warnings{"get-task-warning-1", "get-task-warning-2"}, + expectedErr) + }) + + It("returns the error and outputs all warnings", func() { + Expect(executeErr).To(MatchError(expectedErr)) + + Expect(testUI.Err).To(Say("get-application-warning-1")) + Expect(testUI.Err).To(Say("get-application-warning-2")) + Expect(testUI.Err).To(Say("get-task-warning-1")) + Expect(testUI.Err).To(Say("get-task-warning-2")) + }) + }) + }) + }) + }) + }) +}) diff --git a/command/v7/tasks_command.go b/command/v7/tasks_command.go index 9c3cf8fcdf6..bf5c7c195ec 100644 --- a/command/v7/tasks_command.go +++ b/command/v7/tasks_command.go @@ -14,7 +14,7 @@ type TasksCommand struct { RequiredArgs flag.AppName `positional-args:"yes"` usage interface{} `usage:"CF_NAME tasks APP_NAME"` - relatedCommands interface{} `related_commands:"apps, logs, run-task, terminate-task"` + relatedCommands interface{} `related_commands:"apps, logs, run-task, task, terminate-task"` } func (cmd TasksCommand) Execute(args []string) error { diff --git a/command/v7/terminate_task_command.go b/command/v7/terminate_task_command.go index 0099980f16c..4738b7255af 100644 --- a/command/v7/terminate_task_command.go +++ b/command/v7/terminate_task_command.go @@ -10,7 +10,7 @@ type TerminateTaskCommand struct { RequiredArgs flag.TerminateTaskArgs `positional-args:"yes"` usage interface{} `usage:"CF_NAME terminate-task APP_NAME TASK_ID\n\nEXAMPLES:\n CF_NAME terminate-task my-app 3"` - relatedCommands interface{} `related_commands:"tasks"` + relatedCommands interface{} `related_commands:"tasks, task"` } func (cmd TerminateTaskCommand) Execute(args []string) error { diff --git a/integration/v7/isolated/run_task_command_test.go b/integration/v7/isolated/run_task_command_test.go index cbbdd446eec..6cbbc7a0080 100644 --- a/integration/v7/isolated/run_task_command_test.go +++ b/integration/v7/isolated/run_task_command_test.go @@ -35,7 +35,7 @@ var _ = Describe("run-task command", func() { Expect(session).To(Say(` --name Name to give the task \(generated if omitted\)`)) Expect(session).To(Say(` --process Process type to use as a template for command, memory, and disk for the created task`)) Expect(session).To(Say("SEE ALSO:")) - Expect(session).To(Say(" logs, tasks, terminate-task")) + Expect(session).To(Say(" logs, tasks, task, terminate-task")) }) }) diff --git a/integration/v7/isolated/task_command_test.go b/integration/v7/isolated/task_command_test.go new file mode 100644 index 00000000000..079e1acda47 --- /dev/null +++ b/integration/v7/isolated/task_command_test.go @@ -0,0 +1,127 @@ +package isolated + +import ( + "fmt" + + "code.cloudfoundry.org/cli/integration/helpers" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gbytes" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("task command", func() { + var ( + appName string + ) + + BeforeEach(func() { + appName = helpers.PrefixedRandomName("APP") + }) + + When("--help flag is set", func() { + It("Displays command usage to output", func() { + session := helpers.CF("task", "--help") + Eventually(session).Should(Say("NAME:")) + Eventually(session).Should(Say(" task - Display a task of an app")) + Eventually(session).Should(Say("USAGE:")) + Eventually(session).Should(Say(" cf task APP_NAME TASK_ID")) + Eventually(session).Should(Say("SEE ALSO:")) + Eventually(session).Should(Say(" apps, logs, run-task, tasks, terminate-task")) + Eventually(session).Should(Exit(0)) + }) + }) + + When("the environment is not setup correctly", func() { + It("fails with the appropriate errors", func() { + helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "task", "app-name", "1") + }) + }) + + When("the environment is setup correctly", func() { + var ( + orgName string + spaceName string + ) + + BeforeEach(func() { + orgName = helpers.NewOrgName() + spaceName = helpers.NewSpaceName() + + helpers.SetupCF(orgName, spaceName) + }) + + AfterEach(func() { + helpers.LoginCF() + helpers.QuickDeleteOrg(orgName) + }) + + When("the application does not exist", func() { + It("fails and outputs an app not found message", func() { + session := helpers.CF("task", appName, "1") + Eventually(session).Should(Say("FAILED")) + Eventually(session.Err).Should(Say(fmt.Sprintf("App '%s' not found", appName))) + Eventually(session).Should(Exit(1)) + }) + }) + + When("the application exists", func() { + BeforeEach(func() { + helpers.WithHelloWorldApp(func(appDir string) { + Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0)) + }) + }) + + When("the application does not have the associated task", func() { + It("displays an erro", func() { + session := helpers.CF("task", appName, "1000") + Eventually(session.Err).Should(Say(`Task sequence ID 1000 not found`)) + Eventually(session).Should(Exit(1)) + }) + }) + + When("the application has associated tasks", func() { + BeforeEach(func() { + Eventually(helpers.CF("run-task", appName, "--command", "echo hello world")).Should(Exit(0)) + }) + + It("displays the task", func() { + session := helpers.CF("task", appName, "1") + userName, _ := helpers.GetCredentials() + Eventually(session).Should(Say(fmt.Sprintf("Getting task 1 for app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName))) + + Eventually(session).Should(Say(`id:\s+1`)) + Eventually(session).Should(Say(`name:\s+`)) + Eventually(session).Should(Say(`state:\s+`)) + Eventually(session).Should(Say(`command:\s+echo hello world`)) + + Eventually(session).Should(Exit(0)) + }) + + When("the logged in user does not have authorization to see task commands", func() { + var user string + + BeforeEach(func() { + user = helpers.NewUsername() + password := helpers.NewPassword() + Eventually(helpers.CF("create-user", user, password)).Should(Exit(0)) + Eventually(helpers.CF("set-space-role", user, orgName, spaceName, "SpaceAuditor")).Should(Exit(0)) + helpers.LogoutCF() + env := map[string]string{ + "CF_USERNAME": user, + "CF_PASSWORD": password, + } + Eventually(helpers.CFWithEnv(env, "auth")).Should(Exit(0)) + Eventually(helpers.CF("target", "-o", orgName, "-s", spaceName)).Should(Exit(0)) + }) + + It("displays [hidden] as tasks command", func() { + session := helpers.CF("task", appName, "1") + Eventually(session).Should(Say(`.*command:\s+\[hidden\]`)) + Eventually(session).Should(Exit(0)) + }) + }) + }) + }) + }) +}) diff --git a/integration/v7/isolated/tasks_command_test.go b/integration/v7/isolated/tasks_command_test.go index 8d1bb2d23da..55b37b2e599 100644 --- a/integration/v7/isolated/tasks_command_test.go +++ b/integration/v7/isolated/tasks_command_test.go @@ -27,7 +27,7 @@ var _ = Describe("tasks command", func() { Eventually(session).Should(Say("USAGE:")) Eventually(session).Should(Say(" cf tasks APP_NAME")) Eventually(session).Should(Say("SEE ALSO:")) - Eventually(session).Should(Say(" apps, logs, run-task, terminate-task")) + Eventually(session).Should(Say(" apps, logs, run-task, task, terminate-task")) Eventually(session).Should(Exit(0)) }) }) diff --git a/resources/task_resource.go b/resources/task_resource.go index 62f1f500ed4..6a0184ff865 100644 --- a/resources/task_resource.go +++ b/resources/task_resource.go @@ -32,6 +32,9 @@ type Task struct { // Using a pointer so that it can be set to nil to prevent // json serialization when no template is used Template *TaskTemplate `json:"template,omitempty"` + + // Result contains the task result + Result *TaskResult `json:"result,omitempty"` } type TaskTemplate struct { @@ -41,3 +44,7 @@ type TaskTemplate struct { type TaskProcessTemplate struct { Guid string `json:"guid,omitempty"` } + +type TaskResult struct { + FailureReason string `json:"failure_reason,omitempty"` +} From cb91ff9d70607520574b8995819c0eb34dc90d0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:05:02 -0800 Subject: [PATCH 19/21] [v8](go): Bump the dependencies group with 3 updates (#3317) Bumps the dependencies group with 3 updates: [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo), [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) and [k8s.io/client-go](https://github.com/kubernetes/client-go). Updates `github.com/onsi/ginkgo/v2` from 2.21.0 to 2.22.0 - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.21.0...v2.22.0) Updates `k8s.io/apimachinery` from 0.31.2 to 0.31.3 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.31.2...v0.31.3) Updates `k8s.io/client-go` from 0.31.2 to 0.31.3 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.31.2...v0.31.3) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 397d3b2c00b..11cf9a314ac 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/maxbrunsfeld/counterfeiter/v6 v6.10.0 github.com/moby/term v0.5.0 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d - github.com/onsi/ginkgo/v2 v2.21.0 + github.com/onsi/ginkgo/v2 v2.22.0 github.com/onsi/gomega v1.35.1 github.com/pkg/errors v0.9.1 github.com/sabhiram/go-gitignore v0.0.0-20171017070213-362f9845770f @@ -45,8 +45,8 @@ require ( golang.org/x/text v0.20.0 gopkg.in/cheggaaa/pb.v1 v1.0.28 gopkg.in/yaml.v2 v2.4.0 - k8s.io/apimachinery v0.31.2 - k8s.io/client-go v0.31.2 + k8s.io/apimachinery v0.31.3 + k8s.io/client-go v0.31.3 ) require ( diff --git a/go.sum b/go.sum index 1473e995dbe..b58be82a3eb 100644 --- a/go.sum +++ b/go.sum @@ -197,8 +197,8 @@ github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v0.0.0-20171105031654-1eecca0ba8e6/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -397,12 +397,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.4.0-0.dev/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= -k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= -k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= -k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= -k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= +k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= +k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= +k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= From 6260e37f4910682693a1a90180bc0b47d8e23386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:46:37 -0800 Subject: [PATCH 20/21] [v8](go): Bump the dependencies group with 4 updates (#3323) Bumps the dependencies group with 4 updates: [code.cloudfoundry.org/bytefmt](https://github.com/cloudfoundry/bytefmt), [code.cloudfoundry.org/clock](https://github.com/cloudfoundry/clock), [code.cloudfoundry.org/lager/v3](https://github.com/cloudfoundry/lager) and [github.com/onsi/gomega](https://github.com/onsi/gomega). Updates `code.cloudfoundry.org/bytefmt` from 0.18.0 to 0.19.0 - [Release notes](https://github.com/cloudfoundry/bytefmt/releases) - [Commits](https://github.com/cloudfoundry/bytefmt/compare/v0.18.0...v0.19.0) Updates `code.cloudfoundry.org/clock` from 1.21.0 to 1.22.0 - [Release notes](https://github.com/cloudfoundry/clock/releases) - [Commits](https://github.com/cloudfoundry/clock/compare/v1.21.0...v1.22.0) Updates `code.cloudfoundry.org/lager/v3` from 3.15.0 to 3.16.0 - [Release notes](https://github.com/cloudfoundry/lager/releases) - [Commits](https://github.com/cloudfoundry/lager/compare/v3.15.0...v3.16.0) Updates `github.com/onsi/gomega` from 1.35.1 to 1.36.0 - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.35.1...v1.36.0) --- updated-dependencies: - dependency-name: code.cloudfoundry.org/bytefmt dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/clock dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: code.cloudfoundry.org/lager/v3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 11cf9a314ac..cb3a76beb5d 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,17 @@ module code.cloudfoundry.org/cli go 1.23.1 require ( - code.cloudfoundry.org/bytefmt v0.18.0 + code.cloudfoundry.org/bytefmt v0.19.0 code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 - code.cloudfoundry.org/clock v1.21.0 + code.cloudfoundry.org/clock v1.22.0 code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 code.cloudfoundry.org/go-log-cache/v2 v2.0.7 code.cloudfoundry.org/go-loggregator/v9 v9.2.1 code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f code.cloudfoundry.org/jsonry v1.1.4 - code.cloudfoundry.org/lager/v3 v3.15.0 + code.cloudfoundry.org/lager/v3 v3.16.0 code.cloudfoundry.org/tlsconfig v0.10.0 code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 @@ -32,7 +32,7 @@ require ( github.com/moby/term v0.5.0 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d github.com/onsi/ginkgo/v2 v2.22.0 - github.com/onsi/gomega v1.35.1 + github.com/onsi/gomega v1.36.0 github.com/pkg/errors v0.9.1 github.com/sabhiram/go-gitignore v0.0.0-20171017070213-362f9845770f github.com/sajari/fuzzy v1.0.0 @@ -65,7 +65,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect + github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/go.sum b/go.sum index b58be82a3eb..34fba61f517 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ -code.cloudfoundry.org/bytefmt v0.18.0 h1:bx2J35AAWP4QM7ZGc+yCdQVc15co3O+YpbvMgt7znsI= -code.cloudfoundry.org/bytefmt v0.18.0/go.mod h1:NdqIsywmPwFaEuUArvb9yrBBVjaZBt1onJ8GtElZf6w= +code.cloudfoundry.org/bytefmt v0.19.0 h1:kXnXpABxS5LZtW6aFcpEtNr9Zyr6Zg3iDYGmYqZ+wxc= +code.cloudfoundry.org/bytefmt v0.19.0/go.mod h1:HGXyTS2gCcbWp5Yd38YyqUUuUh6HegIuxiFyHysccTw= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 h1:Yc9r1p21kEpni9WlG4mwOZw87TB2QlyS9sAEebZ3+ak= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6/go.mod h1:u5FovqC5GGAEbFPz+IdjycDA+gIjhUwqxnu0vbHwVeM= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 h1:jaHWw9opYjKPrDT19uydBBWSxl+g5F4Hv030fqMsalo= code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85/go.mod h1:R1EiyOAr7lW0l/YkZNqItUNZ01Q/dYUfbTn4X4Z+82M= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4 h1:O+j8afQWaDuxzKGcculsjgHGK+biBTn6iMjgFpBf54c= code.cloudfoundry.org/cli/integration/assets/hydrabroker v0.0.0-20201002233634-81722a1144e4/go.mod h1:dVTgo9kQbYns/QM4A1C2GtxqUnFSvJTk2Qhw+M0/uzk= -code.cloudfoundry.org/clock v1.21.0 h1:RFRz2iYx9/UynpK7U97a5u5z91t6mr/izP7+0QGtrJw= -code.cloudfoundry.org/clock v1.21.0/go.mod h1:hgxNVpH5uqC1CeVocIe9TKol+jJ3Estd5SNXPk7kMwQ= +code.cloudfoundry.org/clock v1.22.0 h1:wNLKi3vSt0ywYrC1KLOlGYxT6ELwUlWrSpEqe9YczRo= +code.cloudfoundry.org/clock v1.22.0/go.mod h1:wcGQ7OOBfS8oex7J/Xx+nDqfrgWLQFpQHZx9sVDHs5A= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82 h1:Bns1y0jSlcvfP0u8ael+TUlnyNHsNX808zuo58bf5so= code.cloudfoundry.org/diego-ssh v0.0.0-20230810200140-af9d79fe9c82/go.mod h1:L2/glHnSK+wKnsG8oZZqdV2sgYY9NDo/I1aDJGhcWaM= code.cloudfoundry.org/go-log-cache/v2 v2.0.7 h1:yR/JjQ/RscO1n4xVAT9HDYcpx5ET/3Cq2/RhpJml6ZU= @@ -21,8 +21,8 @@ code.cloudfoundry.org/inigo v0.0.0-20230612153013-b300679e6ed6/go.mod h1:1ZB1JCh code.cloudfoundry.org/jsonry v1.1.4 h1:P9N7IlH1/4aRCLcXLgLFj1hkcBmV7muijJzY+K6U4hE= code.cloudfoundry.org/jsonry v1.1.4/go.mod h1:6aKilShQP7w/Ez76h1El2/n9y2OkHuU56nKSBB9Gp0A= code.cloudfoundry.org/lager v1.1.1-0.20191008172124-a9afc05ee5be/go.mod h1:O2sS7gKP3HM2iemG+EnwvyNQK7pTSC6Foi4QiMp9sSk= -code.cloudfoundry.org/lager/v3 v3.15.0 h1:n31lbeh9krwuQLCRUWNEVZBk/BFEtyhQBwDZxFauPw4= -code.cloudfoundry.org/lager/v3 v3.15.0/go.mod h1:x5XGPsP6QF0HMW/FpRilBHu4gy+cWRur8/fiZEyj6z8= +code.cloudfoundry.org/lager/v3 v3.16.0 h1:v7LnlPN+6tiLmE4qHLP4FHRwywRoG3cNE43vIS35O2E= +code.cloudfoundry.org/lager/v3 v3.16.0/go.mod h1:BBAP7NdUAZLLhJhcbjFWX4w4uNpDWgSMMAPc6lX/wT0= code.cloudfoundry.org/tlsconfig v0.10.0 h1:IGbLsOfQmzjI1o5bcGtsTwsZl/Qoz/n5/NkBK68Lk1I= code.cloudfoundry.org/tlsconfig v0.10.0/go.mod h1:Rz8UI6zoOnB9UFxYfPpZhAsl2hDsmjmVW9SGmUhsDSk= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d h1:M+zXqtXJqcsmpL76aU0tdl1ho23eYa4axYoM4gD62UA= @@ -124,8 +124,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs= -github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b h1:SXO0REt4iu865upYCk8aKBBJQ4BqoE0ReP23ClMu60s= +github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -207,8 +207,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= -github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= +github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= From c23186c5bd74408cecf05a311c8b2af59e7dea4d Mon Sep 17 00:00:00 2001 From: h0nIg Date: Mon, 2 Dec 2024 22:08:39 +0100 Subject: [PATCH 21/21] Displaybody should respect new line [v8] (#3151) * display body should respect new line --- util/ui/request_logger_file_writer.go | 2 +- util/ui/request_logger_file_writer_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/util/ui/request_logger_file_writer.go b/util/ui/request_logger_file_writer.go index a2d7aca1e2b..347c556d6cf 100644 --- a/util/ui/request_logger_file_writer.go +++ b/util/ui/request_logger_file_writer.go @@ -29,7 +29,7 @@ func newRequestLoggerFileWriter(ui *UI, lock *sync.Mutex, filePaths []string) *R func (display *RequestLoggerFileWriter) DisplayBody([]byte) error { for _, logFile := range display.logFiles { - _, err := logFile.WriteString(RedactedValue) + _, err := logFile.WriteString(fmt.Sprintf("%s\n", RedactedValue)) if err != nil { return err } diff --git a/util/ui/request_logger_file_writer_test.go b/util/ui/request_logger_file_writer_test.go index 780497bec0d..40f768f64c4 100644 --- a/util/ui/request_logger_file_writer_test.go +++ b/util/ui/request_logger_file_writer_test.go @@ -54,11 +54,11 @@ var _ = Describe("Request Logger File Writer", func() { contents, err := os.ReadFile(logFile1) Expect(err).ToNot(HaveOccurred()) - Expect(string(contents)).To(Equal(RedactedValue + "\n")) + Expect(string(contents)).To(Equal(RedactedValue + "\n\n")) contents, err = os.ReadFile(logFile2) Expect(err).ToNot(HaveOccurred()) - Expect(string(contents)).To(Equal(RedactedValue + "\n")) + Expect(string(contents)).To(Equal(RedactedValue + "\n\n")) }) })