├── .github ├── ISSUE_TEMPLATE │ └── issue-template.md └── workflows │ ├── check-commit-message.yml │ ├── codeql.yml │ └── pull-request-build.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── Roadmap.adoc ├── build.sh ├── cfg └── VERSION ├── cli └── fakes │ └── fake_cli_connection_builder.go ├── clients ├── baseclient │ ├── base_client.go │ ├── baseclient_suite_test.go │ ├── client_error.go │ ├── client_util.go │ ├── client_util_test.go │ └── token_factory.go ├── cfrestclient │ ├── cloud_foundry_operations_extended.go │ ├── fakes │ │ └── fake_cloud_foundry_client.go │ ├── resilient │ │ └── resilient_rest_cloud_foundry_client_extended.go │ └── rest_cloud_foundry_client_extended.go ├── client_factory.go ├── clients_suite_test.go ├── csrf │ ├── csrf_helper.go │ ├── csrf_parameters │ │ └── csrf_request_header.go │ ├── csrf_suite_test.go │ ├── csrf_token_fetcher.go │ ├── csrf_token_manager.go │ ├── csrf_token_manager_test.go │ ├── default_csrf_token_fetcher.go │ ├── default_csrf_token_manager.go │ ├── fakes │ │ └── fake_csrf_token_fetcher.go │ └── transport.go ├── models │ ├── cf_apps_response.go │ ├── cf_services_response.go │ ├── error_type.go │ ├── file_metadata.go │ ├── get_mta_files_o_k_body.go │ ├── get_mta_operation_logs_o_k_body.go │ ├── get_mta_operations_o_k_body.go │ ├── get_mtas_o_k_body.go │ ├── http_response_error.go │ ├── info.go │ ├── inline_response200.go │ ├── log.go │ ├── message.go │ ├── message_type.go │ ├── metadata.go │ ├── module.go │ ├── mta.go │ ├── mta_modules.go │ ├── operation.go │ ├── operation_messages.go │ ├── paginated_response.go │ └── state.go ├── mtaclient │ ├── fakes │ │ ├── fake_mta_client_builder.go │ │ └── fake_mta_client_operations.go │ ├── http_mta_client.go │ ├── mta_client_operations.go │ ├── mta_rest_client.go │ ├── operations │ │ ├── execute_operation_action_parameters.go │ │ ├── execute_operation_action_responses.go │ │ ├── get_csrf_token_parameters.go │ │ ├── get_csrf_token_responses.go │ │ ├── get_info_parameters.go │ │ ├── get_info_responses.go │ │ ├── get_mta_files_parameters.go │ │ ├── get_mta_files_responses.go │ │ ├── get_mta_operation_log_content_parameters.go │ │ ├── get_mta_operation_log_content_responses.go │ │ ├── get_mta_operation_logs_parameters.go │ │ ├── get_mta_operation_logs_responses.go │ │ ├── get_mta_operation_parameters.go │ │ ├── get_mta_operation_responses.go │ │ ├── get_mta_operations_parameters.go │ │ ├── get_mta_operations_responses.go │ │ ├── get_mta_parameters.go │ │ ├── get_mta_responses.go │ │ ├── get_mtas_parameters.go │ │ ├── get_mtas_responses.go │ │ ├── get_operation_actions_parameters.go │ │ ├── get_operation_actions_responses.go │ │ ├── operations_client.go │ │ ├── start_mta_operation_parameters.go │ │ └── start_mta_operation_responses.go │ └── retryable_mta_rest_client.go ├── mtaclient_v2 │ ├── fakes │ │ ├── fake_mta_v2_client_builder.go │ │ └── fake_mta_v2_client_operations.go │ ├── http_mta_v2_client.go │ ├── mta_v2_client_operations.go │ ├── mta_v2_rest_client.go │ ├── operations │ │ ├── get_mtas_v2_parameters.go │ │ ├── get_mtas_v2_responses.go │ │ └── operations_client.go │ └── retryable_mta_v2_rest_client.go ├── restclient │ ├── fakes │ │ ├── fake_rest_client_builder.go │ │ └── fake_rest_client_operations.go │ ├── http_rest_client.go │ ├── operations │ │ ├── get_csrf_token_parameters.go │ │ ├── get_csrf_token_responses.go │ │ ├── operations_client.go │ │ ├── purge_configuration_parameters.go │ │ └── purge_configuration_responses.go │ ├── rest_client.go │ ├── rest_client_operations.go │ ├── rest_client_test.go │ ├── restclient_suite_test.go │ ├── retryable_rest_client.go │ └── retryable_rest_client_test.go └── swagger │ ├── mta_rest.yaml │ └── rest.yaml ├── commands ├── action.go ├── action_test.go ├── base_command.go ├── base_command_test.go ├── blue_green_deploy_command.go ├── command.go ├── commands_suite_test.go ├── default_token_factory.go ├── deploy_command.go ├── deploy_command_test.go ├── deployment_strategy.go ├── deployment_strategy_test.go ├── download_mta_op_logs_command.go ├── download_mta_op_logs_command_test.go ├── execution_monitor.go ├── execution_monitor_test.go ├── execution_status.go ├── fakes │ └── fake_process_type_provider.go ├── file_uploader.go ├── file_uploader_test.go ├── flags_parser.go ├── monitor_action.go ├── mta_command.go ├── mta_command_test.go ├── mta_operations_command.go ├── mta_operations_command_test.go ├── mtas_command.go ├── mtas_command_test.go ├── process_type_provider.go ├── purge_config_command.go ├── purge_config_command_test.go ├── retrier │ └── retry_util.go ├── rollback_mta command_test.go ├── rollback_mta_command.go ├── test_client_factory.go ├── test_token_factory.go ├── undeploy_command.go ├── undeploy_command_test.go └── upload_from_url_status.go ├── configuration ├── configuration.go ├── configuration_suite_test.go ├── configuration_test.go └── properties │ ├── backend_url_configurable_property.go │ ├── configurable_property.go │ ├── disable_progress_bar_property.go │ ├── upload_chunk_size_configurable_property.go │ └── upload_chunks_sequentially_property.go ├── go.mod ├── go.sum ├── log └── log.go ├── logo.png ├── multiapps_plugin.go ├── png ├── Slide1-11-26-19_13-28-21-253 └── Slide2-11-26-19_13-28-21-330 ├── regen-client.sh ├── test_resources ├── commands │ ├── extDescriptor.mtaext │ └── mtaArchive.mtar └── util │ └── mtaArchiveNoDescriptor.mtar ├── testutil ├── exiter.go ├── expector.go ├── test_results.go ├── test_token_factory.go ├── transport.go └── ui.go ├── ui └── ui.go └── util ├── archive_builder.go ├── archive_builder_test.go ├── archive_handler.go ├── archive_handler_test.go ├── builders.go ├── builders_test.go ├── cf_command_builder.go ├── cf_command_builder_test.go ├── cf_command_options_util.go ├── cf_command_options_util_test.go ├── cf_context.go ├── cf_context_test.go ├── cf_target.go ├── deploy_service_url_calculator.go ├── digest.go ├── digest_test.go ├── fakes ├── fake_deploy_service_url_calculator.go └── fake_http_simple_executor.go ├── file_splitter.go ├── http_util.go ├── mta_deployment_descriptor.go ├── mta_manifest.go ├── mta_version_handler.go ├── named_read_seeker.go └── util_suite_test.go /.github/ISSUE_TEMPLATE/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue Template 3 | about: MultiApps CF CLI Plugin issue template for bugs and feature requests 4 | 5 | --- 6 | 7 | ### Description 8 | Describe your issue here. What is the expected behavior? What is the actual behavior? 9 | 10 | ### Your environment 11 | * MultiApps Controller version - 12 | * MultiApps CF CLI Plugin version - 13 | * which CF vendor is used - 14 | * which backing services are used - 15 | 16 | ### Steps to reproduce 17 | Tell us how to reproduce this issue. 18 | Create [GIST(s)](https://gist.github.com/) with the command's output 19 | Create [GIST(s)](https://gist.github.com/) which is copy of your deployment and extension descriptor and link here (if applicable) 20 | 21 | ### Additional information 22 | 23 | If an multi-target app operation fails, download logs of the operation and provide them as a [GIST(s)](https://gist.github.com/). For more details, see *download-mta-op-logs / dmol* command provided by [CF MTA Plugin](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin). The most important log file is *MAIN_LOG*. 24 | -------------------------------------------------------------------------------- /.github/workflows/check-commit-message.yml: -------------------------------------------------------------------------------- 1 | name: Check Commit Message for "LMCROSSITXSADEPLOY" 2 | 3 | on: 4 | pull_request: 5 | types: [synchronize, opened] 6 | 7 | jobs: 8 | check_commit_message: 9 | name: Check Commit Message 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Check Commit Message 14 | id: commits 15 | uses: actions/github-script@v6 16 | with: 17 | script: | 18 | const prNumber = context.payload.pull_request.number; 19 | const commits = await github.rest.pulls.listCommits({ 20 | owner: context.repo.owner, 21 | repo: context.repo.repo, 22 | pull_number: prNumber 23 | }); 24 | 25 | let containsText = false; 26 | for (const commitData of commits.data) { 27 | if (commitData.commit.message.includes("LMCROSSITXSADEPLOY")) { 28 | containsText = true; 29 | break; 30 | } 31 | } 32 | 33 | if (!containsText) { 34 | core.setFailed("❌ Check Commit Message - Failed: At least one commit must contain the word 'LMCROSSITXSADEPLOY'."); 35 | } -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ "master" ] 9 | schedule: 10 | - cron: '30 10 * * 4' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | # Runner size impacts CodeQL analysis time. To learn more, please see: 16 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 17 | # - https://gh.io/supported-runners-and-hardware-resources 18 | # - https://gh.io/using-larger-runners 19 | # Consider using larger runners for possible analysis time improvements. 20 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 21 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 22 | permissions: 23 | actions: read 24 | contents: read 25 | security-events: write 26 | 27 | strategy: 28 | fail-fast: false 29 | matrix: 30 | language: [ 'go' ] 31 | 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v3 35 | 36 | # Initializes the CodeQL tools for scanning. 37 | - name: Initialize CodeQL 38 | uses: github/codeql-action/init@v2 39 | with: 40 | languages: ${{ matrix.language }} 41 | 42 | - name: Autobuild 43 | uses: github/codeql-action/autobuild@v2 44 | 45 | - name: Perform CodeQL Analysis 46 | uses: github/codeql-action/analyze@v2 47 | with: 48 | category: "/language:${{matrix.language}}" 49 | -------------------------------------------------------------------------------- /.github/workflows/pull-request-build.yml: -------------------------------------------------------------------------------- 1 | name: Multiapps CLI Plugin build 2 | 3 | on: 4 | pull_request: 5 | branches: [ master ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | 13 | - name: Set up Go 14 | uses: actions/setup-go@v3 15 | with: 16 | go-version: '1.24' 17 | 18 | - name: Download dependencies 19 | run: go get -d -t ./... 20 | 21 | - name: Build 22 | run: go build -v ./... 23 | 24 | - name: Test 25 | run: go test -v ./... 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | tmp/ 3 | vendor/ 4 | out/ 5 | cf-cli-plugin 6 | mta-op-*/ 7 | .DS_Store 8 | */.DS_Store 9 | .idea 10 | multiapps-plugin.win32.exe 11 | multiapps-plugin.win64.exe 12 | multiapps-plugin.linux32 13 | multiapps-plugin.linux64 14 | multiapps-plugin.osx 15 | multiapps-plugin.linuxarm64 16 | multiapps-plugin.osxarm64 17 | multiapps-plugin-static.linux32 18 | multiapps-plugin-static.linux64 19 | multiapps-plugin-static.linuxarm64 20 | multiapps-plugin-static.osx 21 | multiapps-plugin-static.osxarm64 22 | *.exe 23 | 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.15.2 4 | install: 5 | - chmod +x bin/test.sh 6 | - chmod +x build.sh 7 | - go get -t -v ./... 8 | script: bin/test.sh 9 | branches: 10 | only: 11 | - master 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the MultiApps CF CLI Plugin 2 | 3 | ## Did you find a bug? 4 | * Check if the bug has already been reported and has an open [Issue](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/issues). 5 | 6 | * If there is none, create one by using the provided [Issue Template](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/issues/new/choose) for bugs. 7 | 8 | * Try to be as detailed as possible when describing the bug. Every bit of information helps! 9 | 10 | ## Do you have a question or need support? 11 | If you need any support or have any questions regarding the project, you can drop us a message on [Slack](https://cloudfoundry.slack.com/?redir=%2Fmessages%2Fmultiapps-dev) or open an [Issue](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/issues) and we shall get back to you. 12 | 13 | ## Do you want to contribute to the code base? 14 | 15 | ### Starter GitHub Issues 16 | If you are looking for what you can contribute to the project, check the GitHub Issues labeled as [Good First Issue](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to find items that are marked as more beginner friendly. 17 | 18 | ### Fork the project 19 | * To develop your contribution to the project, first [fork](https://help.github.com/articles/fork-a-repo/) this repository in your own github account. 20 | 21 | * To clone the project into your Go workspace check the [Cloning the repository](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin#cloning-the-repository) section. 22 | 23 | * When developing make sure to keep your fork up to date with the origin's master branch or the release branch you want to contribute a fix to. 24 | 25 | ### How to build, develop and install? 26 | * To build a new version of the plugin follow the [Development](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin#development) instructions. 27 | 28 | * If you have added new dependencies into the CF plugin make sure to update them as described in the [Adding Dependencies](https://github.com/cloudfoundry-incubator//multiapps-cli-plugin#adding-dependency-into-the-multiapps-cli-plugin). 29 | 30 | * To install the plugin follow the [Installation](https://github.com/cloudfoundry-incubator//multiapps-cli-plugin#installation) instructions. 31 | 32 | ### Testing 33 | * Running the tests is done with the [ginkgo](https://github.com/onsi/ginkgo) framework. Once you have it installed just execute `ginkgo -r` from the project's root directory and it will run all the tests. 34 | 35 | * If you are developing new functionality make sure to add tests covering the new scenarios where applicable! 36 | 37 | * The [spring-music](https://github.com/nvvalchev/spring-music) contains a handy sample MTA archive to test your MultiApps CF CLI Plugin against the MultiApps Controller. 38 | 39 | ### Formatting 40 | Having the same style of formatting across the project helps a lot with readability. To format the project's source code run the following command from the root directory of the project: 41 | ``` 42 | gofmt -w cli clients commands testutil ui util 43 | ``` 44 | 45 | ## Creating a pull request 46 | When creating a pull request please use the provided template. Don't forget to link the [Issue](https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/issues) if there is one related to your pull request! 47 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-Present CloudFoundry.org Foundation, Inc. All Rights Reserved. 2 | This project contains software that is Copyright (c) 2015-2018 SAP SE or an SAP affiliate company. 3 | 4 | This project is licensed to you under the Apache License, Version 2.0 (the "License"). 5 | You may not use this project except in compliance with the License. 6 | 7 | This project may include a number of subcomponents with separate copyright notices 8 | and license terms. Your use of these subcomponents is subject to the terms and 9 | conditions of the subcomponent's license, as noted in the LICENSE file. 10 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### Description: 2 | 7 | 8 | 9 | #### Issue: 10 | 11 | -------------------------------------------------------------------------------- /Roadmap.adoc: -------------------------------------------------------------------------------- 1 | # Project multiapps roadmap highlights 2 | 3 | # Current status & short-term priorities can be traked on this repo's link:https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/projects/1[project kanban board ] 4 | 5 | 6 | ## Outlook 7 | image::png/Slide1-11-26-19_13-28-21-253[outlook_snapshot_nov19] 8 | 9 | ### Features: 10 | - dependencies between services (credential/service keys sharing between orchestrated service instances) 11 | - deploy namespaces (same mta, multiple instances within a space) 12 | - explicit modelling for service keys (currently only modelled as part of a service instance creation/update) 13 | 14 | ### CF features / covering multiapps ocrhestration gaps on the CF Api: 15 | - rolling deployment for both deploy/bg-deploy scenario (deployment resource) 16 | - service sharing 17 | - route services 18 | - modelling CF metadata 19 | - support for host-less routes 20 | 21 | ### Other: 22 | - adoption of cf v.7 cli 23 | - d-s discovery via the service broker api 24 | - mta-id based cli interface (instead of process-id) 25 | - blue-green deploy keeping original app names 26 | - additional performance improvements (via caching of hashes, skipping operations) 27 | - loggregator v2 api support 28 | - autoscaling on high load (> 300 deploys/hour) 29 | - repository with multiapps examples on github.com 30 | 31 | ## History 32 | image::png/Slide2-11-26-19_13-28-21-330[achievements_snapshot_nov19] 33 | 34 | ### Features: 35 | - ‘hooks’ functionality, allowing to execute cf tasks on apps in different moments during deployment. Allows for orchestration of e.g. graceful shutdown or any on-update activities – e.g. triggering update of dependent tenant aware services. 36 | - partial deploy - ability to process only selected parts of the mta 37 | - many improvements toward deployment configuration (parameters) handling 38 | - configurable restart on app environment change 39 | - signature checking for deployed content 40 | - IDE editor support for the descriptors in VSCode & InteliJ (via static schemastore.org validation & auto-complete) 41 | - additional parallelization, after parallel app deployment was done – for service instnances and app deletion in bg-deploy scenarios. 42 | - configurable persistent state of service bindings / env vars / routes - merging existing deployment’s with the targeted’s 43 | 44 | ### Adopted CF features / covering orchestration gaps of our on the CF Api: 45 | - adoption of the CC V3 api 46 | - buildpacks (plural) support 47 | - reuse default domain value from CC 48 | 49 | ### mics 50 | - new https://github.com/SAP/cloud-mta-build-tool[cloud mta build tool] - OSS tool for buld & assembly of MTA archives! 51 | 52 | 53 | ### Stability/resilience/performance improvements: 54 | - automatic retry of deployments on certain types of failure 55 | - handling backing service state during deployment e.g. last operation ‘in progress‘ 56 | - support for up-to 4GB deployables 57 | - regularly executed load & stress tests 58 | - azure object store persistence 59 | - rate limiting 60 | -------------------------------------------------------------------------------- /cfg/VERSION: -------------------------------------------------------------------------------- 1 | 3.5.0 2 | -------------------------------------------------------------------------------- /cli/fakes/fake_cli_connection_builder.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import ( 4 | plugin_models "code.cloudfoundry.org/cli/plugin/models" 5 | fakes "code.cloudfoundry.org/cli/plugin/pluginfakes" 6 | ) 7 | 8 | // FakeCliConnectionBuilder is a builder of FakeCliConnection instances 9 | type FakeCliConnectionBuilder struct { 10 | cliConn fakes.FakeCliConnection 11 | } 12 | 13 | // NewFakeCliConnectionBuilder creates a new builder 14 | func NewFakeCliConnectionBuilder() *FakeCliConnectionBuilder { 15 | return &FakeCliConnectionBuilder{} 16 | } 17 | 18 | func (b *FakeCliConnectionBuilder) CurrentOrg(guid, name string, err error) *FakeCliConnectionBuilder { 19 | org := plugin_models.Organization{OrganizationFields: plugin_models.OrganizationFields{Guid: guid, Name: name}} 20 | b.cliConn.GetCurrentOrgReturns(org, err) 21 | return b 22 | } 23 | 24 | func (b *FakeCliConnectionBuilder) CurrentSpace(guid, name string, err error) *FakeCliConnectionBuilder { 25 | space := plugin_models.Space{SpaceFields: plugin_models.SpaceFields{Guid: guid, Name: name}} 26 | b.cliConn.GetCurrentSpaceReturns(space, err) 27 | return b 28 | } 29 | 30 | func (b *FakeCliConnectionBuilder) Username(username string, err error) *FakeCliConnectionBuilder { 31 | b.cliConn.UsernameReturns(username, err) 32 | return b 33 | } 34 | 35 | func (b *FakeCliConnectionBuilder) AccessToken(token string, err error) *FakeCliConnectionBuilder { 36 | b.cliConn.AccessTokenReturns(token, err) 37 | return b 38 | } 39 | 40 | func (b *FakeCliConnectionBuilder) APIEndpoint(apiURL string, err error) *FakeCliConnectionBuilder { 41 | b.cliConn.ApiEndpointReturns(apiURL, err) 42 | return b 43 | } 44 | 45 | func (b *FakeCliConnectionBuilder) GetApp(name string, app plugin_models.GetAppModel, err error) *FakeCliConnectionBuilder { 46 | b.cliConn.GetAppReturns(app, err) // TODO 47 | return b 48 | } 49 | 50 | func (b *FakeCliConnectionBuilder) GetApps(apps []plugin_models.GetAppsModel, err error) *FakeCliConnectionBuilder { 51 | b.cliConn.GetAppsReturns(apps, err) 52 | return b 53 | } 54 | 55 | func (b *FakeCliConnectionBuilder) GetService(name string, service plugin_models.GetService_Model, err error) *FakeCliConnectionBuilder { 56 | b.cliConn.GetServiceReturns(service, err) // TODO 57 | return b 58 | } 59 | 60 | func (b *FakeCliConnectionBuilder) GetServices(services []plugin_models.GetServices_Model, err error) *FakeCliConnectionBuilder { 61 | b.cliConn.GetServicesReturns(services, err) 62 | return b 63 | } 64 | 65 | func (b *FakeCliConnectionBuilder) GetSpace(name string, space plugin_models.GetSpace_Model, err error) *FakeCliConnectionBuilder { 66 | b.cliConn.GetSpaceReturns(space, err) // TODO 67 | return b 68 | } 69 | 70 | // Build builds a FakeCliConnection instance 71 | func (b *FakeCliConnectionBuilder) Build() *fakes.FakeCliConnection { 72 | return &b.cliConn 73 | } 74 | -------------------------------------------------------------------------------- /clients/baseclient/base_client.go: -------------------------------------------------------------------------------- 1 | package baseclient 2 | 3 | import ( 4 | "net/http" 5 | "net/http/cookiejar" 6 | 7 | "github.com/go-openapi/runtime" 8 | "github.com/go-openapi/runtime/client" 9 | ) 10 | 11 | var schemes = []string{"http", "https"} 12 | 13 | // BaseClient represents a base SLP client 14 | type BaseClient struct { 15 | TokenFactory TokenFactory 16 | } 17 | 18 | // GetTokenFactory returns the authentication info 19 | func (c *BaseClient) GetTokenFactory() TokenFactory { 20 | return c.TokenFactory 21 | } 22 | 23 | // SetTokenFactory sets the authentication info 24 | func (c *BaseClient) SetTokenFactory(tokenFactory TokenFactory) { 25 | c.TokenFactory = tokenFactory 26 | } 27 | 28 | // NewHTTPTransport creates a new HTTP transport 29 | func NewHTTPTransport(host, url string, rt http.RoundTripper) *client.Runtime { 30 | // TODO: apply the changes made by Boyan here, as after the update of the dependencies the changes are not available 31 | transport := client.New(host, url, schemes) 32 | transport.Consumers["text/html"] = runtime.TextConsumer() 33 | transport.Transport = rt 34 | jar, _ := cookiejar.New(nil) 35 | transport.Jar = jar 36 | return transport 37 | } 38 | -------------------------------------------------------------------------------- /clients/baseclient/baseclient_suite_test.go: -------------------------------------------------------------------------------- 1 | package baseclient_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestBaseclient(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Baseclient Suite") 13 | } 14 | -------------------------------------------------------------------------------- /clients/baseclient/client_error.go: -------------------------------------------------------------------------------- 1 | package baseclient 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/go-openapi/strfmt" 9 | 10 | "github.com/go-openapi/runtime" 11 | ) 12 | 13 | type ClientError struct { 14 | Code int 15 | Status string 16 | Description interface{} 17 | } 18 | 19 | func (ce *ClientError) Error() string { 20 | return fmt.Sprintf("%s (status %d): %v ", ce.Status, ce.Code, ce.Description) 21 | } 22 | 23 | func NewClientError(err error) error { 24 | if err == nil { 25 | return nil 26 | } 27 | ae, ok := err.(*runtime.APIError) 28 | if ok { 29 | response := ae.Response.(runtime.ClientResponse) 30 | return &ClientError{Code: ae.Code, Status: response.Message(), Description: response.Message()} 31 | } 32 | response, ok := err.(*ErrorResponse) 33 | if ok { 34 | return &ClientError{Code: response.Code, Status: response.Status, Description: response.Payload} 35 | } 36 | return err 37 | } 38 | 39 | func BuildErrorResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 40 | result := &ErrorResponse{ 41 | Code: response.Code(), 42 | Status: response.Message(), // this isn't the body! 43 | } 44 | if err := result.readResponse(response, consumer, formats); err != nil { 45 | return err 46 | } 47 | return result 48 | } 49 | 50 | // ErrorResponse handles error cases 51 | type ErrorResponse struct { 52 | Code int 53 | Status string 54 | Payload string 55 | } 56 | 57 | func (e *ErrorResponse) Error() string { 58 | return fmt.Sprintf("%s (status %d): %v ", e.Status, e.Code, e.Payload) 59 | } 60 | 61 | func (e *ErrorResponse) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 62 | buf := new(bytes.Buffer) 63 | _, err := buf.ReadFrom(response.Body()) 64 | if err != nil { 65 | return runtime.NewAPIError("unknown error", response, response.Code()) 66 | } 67 | e.Payload = buf.String() 68 | 69 | return nil 70 | } 71 | 72 | type RetryAfterError struct { 73 | Duration time.Duration 74 | } 75 | 76 | func (e *RetryAfterError) Error() string { 77 | return "Retryable error: Retry-After " + e.Duration.String() 78 | } 79 | -------------------------------------------------------------------------------- /clients/baseclient/client_util.go: -------------------------------------------------------------------------------- 1 | package baseclient 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 7 | ) 8 | 9 | // CallWithRetry executes callback with retry 10 | func CallWithRetry(callback func() (interface{}, error), maxRetriesCount int, retryInterval time.Duration) (interface{}, error) { 11 | for index := 0; index < maxRetriesCount; index++ { 12 | resp, err := callback() 13 | if !shouldRetry(err) { 14 | return resp, err 15 | } 16 | retryErr, ok := err.(*RetryAfterError) 17 | if ok { 18 | ui.Warn("Retryable error occurred. Retrying after %s", retryErr.Duration) 19 | time.Sleep(retryErr.Duration) 20 | continue 21 | } 22 | ui.Warn("Error occurred: %s. Retrying after: %s.", err.Error(), retryInterval) 23 | time.Sleep(retryInterval) 24 | } 25 | return callback() 26 | } 27 | 28 | func shouldRetry(err error) bool { 29 | if err == nil { 30 | return false 31 | } 32 | ae, ok := err.(*ClientError) 33 | if ok { 34 | httpCode := ae.Code 35 | httpCodeMajorDigit := httpCode / 100 36 | return httpCodeMajorDigit != 2 37 | } 38 | return true 39 | } 40 | -------------------------------------------------------------------------------- /clients/baseclient/token_factory.go: -------------------------------------------------------------------------------- 1 | package baseclient 2 | 3 | import "github.com/go-openapi/runtime" 4 | 5 | // TokenFactory factory for generating new OAuth token 6 | type TokenFactory interface { 7 | NewToken() (runtime.ClientAuthInfoWriter, error) 8 | NewRawToken() (string, error) 9 | } 10 | -------------------------------------------------------------------------------- /clients/cfrestclient/cloud_foundry_operations_extended.go: -------------------------------------------------------------------------------- 1 | package cfrestclient 2 | 3 | import ( 4 | models "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 5 | ) 6 | 7 | type CloudFoundryOperationsExtended interface { 8 | GetApplications(mtaId, mtaNamespace, spaceGuid string) ([]models.CloudFoundryApplication, error) 9 | GetAppProcessStatistics(appGuid string) ([]models.ApplicationProcessStatistics, error) 10 | GetApplicationRoutes(appGuid string) ([]models.ApplicationRoute, error) 11 | GetServiceInstances(mtaId, mtaNamespace, spaceGuid string) ([]models.CloudFoundryServiceInstance, error) 12 | GetServiceBindings(serviceName string) ([]models.ServiceBinding, error) 13 | } 14 | -------------------------------------------------------------------------------- /clients/cfrestclient/fakes/fake_cloud_foundry_client.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 4 | 5 | type FakeCloudFoundryClient struct { 6 | Apps []models.CloudFoundryApplication 7 | AppsErr error 8 | AppProcessStats []models.ApplicationProcessStatistics 9 | AppProcessStatsErr error 10 | AppRoutes []models.ApplicationRoute 11 | AppRoutesErr error 12 | Services []models.CloudFoundryServiceInstance 13 | ServicesErr error 14 | ServiceBindings []models.ServiceBinding 15 | ServiceBindingsErr error 16 | } 17 | 18 | func (f FakeCloudFoundryClient) GetApplications(mtaId, mtaNamespace, spaceGuid string) ([]models.CloudFoundryApplication, error) { 19 | return f.Apps, f.AppsErr 20 | } 21 | 22 | func (f FakeCloudFoundryClient) GetAppProcessStatistics(appGuid string) ([]models.ApplicationProcessStatistics, error) { 23 | return f.AppProcessStats, f.AppProcessStatsErr 24 | } 25 | 26 | func (f FakeCloudFoundryClient) GetApplicationRoutes(appGuid string) ([]models.ApplicationRoute, error) { 27 | return f.AppRoutes, f.AppRoutesErr 28 | } 29 | 30 | func (f FakeCloudFoundryClient) GetServiceInstances(mtaId, mtaNamespace, spaceGuid string) ([]models.CloudFoundryServiceInstance, error) { 31 | return f.Services, f.ServicesErr 32 | } 33 | 34 | func (f FakeCloudFoundryClient) GetServiceBindings(serviceName string) ([]models.ServiceBinding, error) { 35 | return f.ServiceBindings, f.ServiceBindingsErr 36 | } 37 | -------------------------------------------------------------------------------- /clients/cfrestclient/resilient/resilient_rest_cloud_foundry_client_extended.go: -------------------------------------------------------------------------------- 1 | package resilient 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/cfrestclient" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 6 | "time" 7 | ) 8 | 9 | type ResilientCloudFoundryRestClient struct { 10 | CloudFoundryRestClient cfrestclient.CloudFoundryOperationsExtended 11 | MaxRetriesCount int 12 | RetryInterval time.Duration 13 | } 14 | 15 | func NewResilientCloudFoundryClient(cloudFoundryRestClient cfrestclient.CloudFoundryOperationsExtended, maxRetriesCount int, retryIntervalInSeconds int) cfrestclient.CloudFoundryOperationsExtended { 16 | return &ResilientCloudFoundryRestClient{cloudFoundryRestClient, maxRetriesCount, time.Second * time.Duration(retryIntervalInSeconds)} 17 | } 18 | 19 | func (c ResilientCloudFoundryRestClient) GetApplications(mtaId, mtaNamespace, spaceGuid string) ([]models.CloudFoundryApplication, error) { 20 | return retryOnError(func() ([]models.CloudFoundryApplication, error) { 21 | return c.CloudFoundryRestClient.GetApplications(mtaId, mtaNamespace, spaceGuid) 22 | }, c.MaxRetriesCount, c.RetryInterval) 23 | } 24 | 25 | func (c ResilientCloudFoundryRestClient) GetAppProcessStatistics(appGuid string) ([]models.ApplicationProcessStatistics, error) { 26 | return retryOnError(func() ([]models.ApplicationProcessStatistics, error) { 27 | return c.CloudFoundryRestClient.GetAppProcessStatistics(appGuid) 28 | }, c.MaxRetriesCount, c.RetryInterval) 29 | } 30 | 31 | func (c ResilientCloudFoundryRestClient) GetApplicationRoutes(appGuid string) ([]models.ApplicationRoute, error) { 32 | return retryOnError(func() ([]models.ApplicationRoute, error) { 33 | return c.CloudFoundryRestClient.GetApplicationRoutes(appGuid) 34 | }, c.MaxRetriesCount, c.RetryInterval) 35 | } 36 | 37 | func (c ResilientCloudFoundryRestClient) GetServiceInstances(mtaId, mtaNamespace, spaceGuid string) ([]models.CloudFoundryServiceInstance, error) { 38 | return retryOnError(func() ([]models.CloudFoundryServiceInstance, error) { 39 | return c.CloudFoundryRestClient.GetServiceInstances(mtaId, mtaNamespace, spaceGuid) 40 | }, c.MaxRetriesCount, c.RetryInterval) 41 | } 42 | 43 | func (c ResilientCloudFoundryRestClient) GetServiceBindings(serviceName string) ([]models.ServiceBinding, error) { 44 | return retryOnError(func() ([]models.ServiceBinding, error) { 45 | return c.CloudFoundryRestClient.GetServiceBindings(serviceName) 46 | }, c.MaxRetriesCount, c.RetryInterval) 47 | } 48 | 49 | func retryOnError[T any](operation func() (T, error), retries int, retryInterval time.Duration) (T, error) { 50 | result, err := operation() 51 | for shouldRetry(retries, err) { 52 | time.Sleep(retryInterval) 53 | retries-- 54 | result, err = operation() 55 | } 56 | return result, err 57 | } 58 | 59 | func shouldRetry(retries int, err error) bool { 60 | _, isResponseError := err.(models.HttpResponseError) 61 | return isResponseError && retries > 0 62 | } 63 | -------------------------------------------------------------------------------- /clients/client_factory.go: -------------------------------------------------------------------------------- 1 | package clients 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient_v2" 9 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/restclient" 10 | ) 11 | 12 | // ClientFactory is a factory for creating XxxClientOperations instances 13 | type ClientFactory interface { 14 | NewMtaClient(host, spaceID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) mtaclient.MtaClientOperations 15 | NewRestClient(host string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) restclient.RestClientOperations 16 | NewMtaV2Client(host, spaceGUID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) mtaclient_v2.MtaV2ClientOperations 17 | } 18 | 19 | // DefaultClientFactory a default implementation of the ClientFactory 20 | type DefaultClientFactory struct { 21 | mtaClient mtaclient.MtaClientOperations 22 | restClient restclient.RestClientOperations 23 | mtaV2Client mtaclient_v2.MtaV2ClientOperations 24 | } 25 | 26 | // NewDefaultClientFactory a default initialization method for the factory 27 | func NewDefaultClientFactory() *DefaultClientFactory { 28 | return &DefaultClientFactory{mtaClient: nil, restClient: nil} 29 | } 30 | 31 | // NewMtaClient used for creating or returning cached value of the mta rest client 32 | func (d *DefaultClientFactory) NewMtaClient(host, spaceID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) mtaclient.MtaClientOperations { 33 | if d.mtaClient == nil { 34 | d.mtaClient = mtaclient.NewRetryableMtaRestClient(host, spaceID, rt, tokenFactory) 35 | } 36 | return d.mtaClient 37 | } 38 | 39 | // NewMtaClient used for creating or returning cached value of the mta rest client 40 | func (d *DefaultClientFactory) NewMtaV2Client(host, spaceGUID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) mtaclient_v2.MtaV2ClientOperations { 41 | if d.mtaV2Client == nil { 42 | d.mtaV2Client = mtaclient_v2.NewRetryableMtaRestClient(host, spaceGUID, rt, tokenFactory) 43 | } 44 | return d.mtaV2Client 45 | } 46 | 47 | // NewRestClient used for creating or returning cached value of the rest client 48 | func (d *DefaultClientFactory) NewRestClient(host string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) restclient.RestClientOperations { 49 | if d.restClient == nil { 50 | d.restClient = restclient.NewRetryableRestClient(host, rt, tokenFactory) 51 | } 52 | return d.restClient 53 | } 54 | -------------------------------------------------------------------------------- /clients/clients_suite_test.go: -------------------------------------------------------------------------------- 1 | package clients_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestClients(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Clients Suite") 13 | } 14 | -------------------------------------------------------------------------------- /clients/csrf/csrf_helper.go: -------------------------------------------------------------------------------- 1 | package csrf 2 | 3 | import ( 4 | "net/http" 5 | "sync" 6 | "time" 7 | 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters" 9 | ) 10 | 11 | const CookieHeader = "Cookie" 12 | 13 | type CsrfTokenHelper struct { 14 | Header string 15 | Token string 16 | Cookies []*http.Cookie 17 | NonProtectedMethods map[string]struct{} 18 | LastUpdateTime time.Time 19 | Mutex sync.Mutex 20 | } 21 | 22 | func (c *CsrfTokenHelper) IsProtectionRequired(req *http.Request) bool { 23 | _, present := c.NonProtectedMethods[req.Method] 24 | return !present 25 | } 26 | 27 | func (c *CsrfTokenHelper) IsExpired(timeout time.Duration) bool { 28 | return c.LastUpdateTime.IsZero() || c.LastUpdateTime.Add(timeout).Before(time.Now()) 29 | } 30 | 31 | func (c *CsrfTokenHelper) Update(params csrf_parameters.CsrfParams) { 32 | c.Header = params.CsrfTokenHeader 33 | c.Token = params.CsrfTokenValue 34 | c.Cookies = params.Cookies 35 | c.LastUpdateTime = time.Now() 36 | } 37 | 38 | func (c *CsrfTokenHelper) SetInRequest(req *http.Request) { 39 | req.Header.Set(c.Header, c.Token) 40 | UpdateCookiesIfNeeded(c.Cookies, req) 41 | } 42 | 43 | func (c *CsrfTokenHelper) InvalidateToken() { 44 | c.LastUpdateTime = time.Time{} 45 | } 46 | 47 | func UpdateCookiesIfNeeded(cookies []*http.Cookie, request *http.Request) { 48 | if len(cookies) == 0 { 49 | return 50 | } 51 | request.Header.Del(CookieHeader) 52 | for _, cookie := range cookies { 53 | request.AddCookie(cookie) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /clients/csrf/csrf_parameters/csrf_request_header.go: -------------------------------------------------------------------------------- 1 | package csrf_parameters 2 | 3 | import "net/http" 4 | 5 | type CsrfParams struct { 6 | CsrfTokenHeader string 7 | CsrfTokenValue string 8 | Cookies []*http.Cookie 9 | } 10 | -------------------------------------------------------------------------------- /clients/csrf/csrf_suite_test.go: -------------------------------------------------------------------------------- 1 | package csrf_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestRestclient(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Csrf suite") 13 | } 14 | -------------------------------------------------------------------------------- /clients/csrf/csrf_token_fetcher.go: -------------------------------------------------------------------------------- 1 | package csrf 2 | 3 | import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters" 4 | 5 | type CsrfTokenFetcher interface { 6 | FetchCsrfToken(url, authToken string) (csrf_parameters.CsrfParams, error) 7 | } 8 | -------------------------------------------------------------------------------- /clients/csrf/csrf_token_manager.go: -------------------------------------------------------------------------------- 1 | package csrf 2 | 3 | import "net/http" 4 | 5 | type CsrfTokenManager interface { 6 | updateToken(*http.Request) error 7 | invalidateToken() 8 | } 9 | -------------------------------------------------------------------------------- /clients/csrf/default_csrf_token_fetcher.go: -------------------------------------------------------------------------------- 1 | package csrf 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/log" 9 | ) 10 | 11 | const CsrfTokenHeaderFetchValue = "Fetch" 12 | const CsrfTokenHeaderRequiredValue = "Required" 13 | const CsrfTokensApi = "/api/v1/csrf-token" //also available at /rest/csrf-token 14 | const AuthorizationHeader = "Authorization" 15 | const XCsrfHeader = "X-Csrf-Header" 16 | const XCsrfToken = "X-Csrf-Token" 17 | 18 | type DefaultCsrfTokenFetcher struct { 19 | transport *Transport 20 | } 21 | 22 | func NewDefaultCsrfTokenFetcher(transport *Transport) *DefaultCsrfTokenFetcher { 23 | return &DefaultCsrfTokenFetcher{transport: transport} 24 | } 25 | 26 | func (c *DefaultCsrfTokenFetcher) FetchCsrfToken(url, authToken string) (csrf_parameters.CsrfParams, error) { 27 | fetchTokenRequest, err := http.NewRequest(http.MethodGet, url, nil) 28 | if err != nil { 29 | return csrf_parameters.CsrfParams{}, err 30 | } 31 | fetchTokenRequest.Header.Set(XCsrfToken, CsrfTokenHeaderFetchValue) 32 | fetchTokenRequest.Header.Set(AuthorizationHeader, authToken) 33 | 34 | response, err := c.transport.Delegate.RoundTrip(fetchTokenRequest) 35 | if err != nil { 36 | return csrf_parameters.CsrfParams{}, err 37 | } 38 | 39 | // if there are set-cookie headers present in response - persist them in Transport 40 | cookies := response.Cookies() 41 | if len(cookies) != 0 { 42 | log.Tracef("%s", "Set-Cookie headers present in response, updating current with '"+prettyPrintCookies(cookies)+"'\n") 43 | } 44 | 45 | log.Tracef("%s", "New CSRF Token fetched '"+response.Header.Get(XCsrfToken)+"'\n") 46 | return csrf_parameters.CsrfParams{ 47 | CsrfTokenHeader: response.Header.Get(XCsrfHeader), 48 | CsrfTokenValue: response.Header.Get(XCsrfToken), 49 | Cookies: cookies, 50 | }, nil 51 | } 52 | 53 | func getCsrfTokenUrl(url *url.URL) string { 54 | return url.Scheme + "://" + url.Host + CsrfTokensApi 55 | } 56 | -------------------------------------------------------------------------------- /clients/csrf/default_csrf_token_manager.go: -------------------------------------------------------------------------------- 1 | package csrf 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | const CsrfSessionTimeout = time.Minute + 30*time.Second 9 | 10 | type DefaultCsrfTokenManager struct { 11 | csrfHelper *CsrfTokenHelper 12 | csrfTokenFetcher CsrfTokenFetcher 13 | } 14 | 15 | func NewDefaultCsrfTokenManager(transport *Transport) *DefaultCsrfTokenManager { 16 | return &DefaultCsrfTokenManager{csrfHelper: transport.Csrf, csrfTokenFetcher: NewDefaultCsrfTokenFetcher(transport)} 17 | } 18 | 19 | func NewDefaultCsrfTokenManagerWithFetcher(csrf *CsrfTokenHelper, csrfTokenFetcher CsrfTokenFetcher) *DefaultCsrfTokenManager { 20 | return &DefaultCsrfTokenManager{csrfHelper: csrf, csrfTokenFetcher: csrfTokenFetcher} 21 | } 22 | 23 | func (c *DefaultCsrfTokenManager) updateToken(req *http.Request) error { 24 | if !c.csrfHelper.IsProtectionRequired(req) { 25 | return nil 26 | } 27 | 28 | c.csrfHelper.Mutex.Lock() 29 | defer c.csrfHelper.Mutex.Unlock() 30 | 31 | if c.csrfHelper.IsExpired(CsrfSessionTimeout) { 32 | csrfParams, err := c.csrfTokenFetcher.FetchCsrfToken(getCsrfTokenUrl(req.URL), req.Header.Get(AuthorizationHeader)) 33 | if err != nil { 34 | return err 35 | } 36 | c.csrfHelper.Update(csrfParams) 37 | } 38 | 39 | c.csrfHelper.SetInRequest(req) 40 | return nil 41 | } 42 | 43 | func (c *DefaultCsrfTokenManager) invalidateToken() { 44 | c.csrfHelper.Mutex.Lock() 45 | c.csrfHelper.InvalidateToken() 46 | c.csrfHelper.Mutex.Unlock() 47 | } 48 | -------------------------------------------------------------------------------- /clients/csrf/fakes/fake_csrf_token_fetcher.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters" 4 | 5 | const FakeCsrfTokenHeader = "fake-xcsrf-token-header" 6 | const FakeCsrfTokenValue = "fake-xcsrf-token-value" 7 | 8 | type FakeCsrfTokenFetcher struct{} 9 | 10 | func (c *FakeCsrfTokenFetcher) FetchCsrfToken(string, string) (csrf_parameters.CsrfParams, error) { 11 | return csrf_parameters.CsrfParams{CsrfTokenHeader: FakeCsrfTokenHeader, CsrfTokenValue: FakeCsrfTokenValue}, nil 12 | } 13 | 14 | func NewFakeCsrfTokenFetcher() *FakeCsrfTokenFetcher { 15 | return &FakeCsrfTokenFetcher{} 16 | } 17 | -------------------------------------------------------------------------------- /clients/csrf/transport.go: -------------------------------------------------------------------------------- 1 | package csrf 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "strings" 7 | 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/log" 9 | ) 10 | 11 | type Transport struct { 12 | Delegate http.RoundTripper 13 | Csrf *CsrfTokenHelper 14 | } 15 | 16 | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { 17 | reqCopy := req.Clone(req.Context()) 18 | 19 | csrfTokenManager := NewDefaultCsrfTokenManager(t) 20 | err := csrfTokenManager.updateToken(reqCopy) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | log.Tracef("Sending a request with CSRF %s\n", reqCopy.Header.Get("X-Csrf-Token")) 26 | log.Tracef("Cookies used are: %s\n", prettyPrintCookies(reqCopy.Cookies())) 27 | 28 | resp, err := t.Delegate.RoundTrip(reqCopy) 29 | if err != nil { 30 | return nil, err 31 | } 32 | if isCsrfError(resp) { 33 | csrfTokenManager.invalidateToken() 34 | return nil, errors.New("invalid CSRF token") 35 | } 36 | 37 | return resp, nil 38 | } 39 | 40 | func prettyPrintCookies(cookies []*http.Cookie) string { 41 | var result strings.Builder 42 | for _, cookie := range cookies { 43 | result.WriteString(cookie.String()) 44 | result.WriteRune(' ') 45 | } 46 | return result.String() 47 | } 48 | 49 | func isCsrfError(resp *http.Response) bool { 50 | return resp.StatusCode == http.StatusForbidden && resp.Header.Get(XCsrfToken) == CsrfTokenHeaderRequiredValue 51 | 52 | } 53 | -------------------------------------------------------------------------------- /clients/models/cf_apps_response.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type CloudFoundryApplication struct { 4 | Name string `json:"name"` 5 | Guid string `json:"guid"` 6 | State string `json:"state"` 7 | SpaceGuid string `jsonry:"relationships.space.data.guid"` 8 | } 9 | 10 | type AppProcessStatisticsResponse struct { 11 | Resources []ApplicationProcessStatistics `json:"resources"` 12 | } 13 | 14 | type ApplicationProcessStatistics struct { 15 | State string `json:"state"` 16 | Memory int64 `jsonry:"usage.mem"` 17 | Disk int64 `jsonry:"usage.disk"` 18 | } 19 | 20 | type ApplicationRoute struct { 21 | Host string `json:"host,omitempty"` 22 | Path string `json:"path,omitempty"` 23 | Url string `json:"url"` 24 | } 25 | -------------------------------------------------------------------------------- /clients/models/cf_services_response.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type CloudFoundryServiceInstance struct { 4 | Guid string `json:"guid"` 5 | Name string `json:"name"` 6 | Type string `json:"type"` 7 | Tags []string `json:"tags"` 8 | LastOperation LastOperation `json:"last_operation,omitempty"` 9 | PlanGuid string `jsonry:"relationships.service_plan.data.guid"` 10 | SpaceGuid string `jsonry:"relationships.space.data.guid"` 11 | Metadata Metadata `json:"metadata"` 12 | 13 | Plan ServicePlan `json:"-"` 14 | Offering ServiceOffering `json:"-"` 15 | } 16 | 17 | type LastOperation struct { 18 | Type string `json:"type"` 19 | State string `json:"state"` 20 | Description string `json:"description"` 21 | CreatedAt string `json:"created_at"` 22 | UpdatedAt string `json:"updated_at"` 23 | } 24 | 25 | type ServicePlan struct { 26 | Guid string `json:"guid"` 27 | Name string `json:"name"` 28 | OfferingGuid string `jsonry:"relationships.service_offering.data.guid,omitempty"` 29 | } 30 | 31 | type ServiceOffering struct { 32 | Guid string `json:"guid"` 33 | Name string `json:"name"` 34 | } 35 | 36 | type ServiceBinding struct { 37 | Guid string `json:"guid"` 38 | Name string `json:"name,omitempty"` 39 | AppGuid string `jsonry:"relationships.app.data.guid,omitempty"` 40 | 41 | AppName string `json:"-"` 42 | } 43 | 44 | type ServiceInstanceAuxiliaryContent struct { 45 | ServicePlans []ServicePlan `json:"service_plans"` 46 | ServiceOfferings []ServiceOffering `json:"service_offerings"` 47 | } 48 | 49 | type ServiceBindingAuxiliaryContent struct { 50 | Apps []CloudFoundryApplication `json:"apps"` 51 | } 52 | -------------------------------------------------------------------------------- /clients/models/error_type.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "encoding/json" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // ErrorType error type 18 | // swagger:model ErrorType 19 | type ErrorType string 20 | 21 | const ( 22 | // ErrorTypeCONTENT captures enum value "CONTENT" 23 | ErrorTypeCONTENT = "CONTENT" 24 | // ErrorTypeINFRASTRUCTURE captures enum value "INFRASTRUCTURE" 25 | ErrorTypeINFRASTRUCTURE = "INFRASTRUCTURE" 26 | ) 27 | 28 | // for schema 29 | var errorTypeEnum []interface{} 30 | 31 | func init() { 32 | var res []ErrorType 33 | if err := json.Unmarshal([]byte(`["CONTENT", "INFRASTRCTURE"]`), &res); err != nil { 34 | panic(err) 35 | } 36 | for _, v := range res { 37 | errorTypeEnum = append(errorTypeEnum, v) 38 | } 39 | } 40 | 41 | func (m ErrorType) validateErrorTypeEnum(path, location string, value ErrorType) error { 42 | if err := validate.Enum(path, location, value, errorTypeEnum); err != nil { 43 | return err 44 | } 45 | return nil 46 | } 47 | 48 | // Validate validates this error type 49 | func (m ErrorType) Validate(formats strfmt.Registry) error { 50 | var res []error 51 | 52 | // value enum 53 | if err := m.validateErrorTypeEnum("", "body", m); err != nil { 54 | return err 55 | } 56 | 57 | if len(res) > 0 { 58 | return errors.CompositeValidationError(res...) 59 | } 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /clients/models/file_metadata.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // FileMetadata file metadata 16 | // swagger:model FileMetadata 17 | 18 | type FileMetadata struct { 19 | 20 | // digest 21 | Digest string `json:"digest,omitempty"` 22 | 23 | // digest algorithm 24 | DigestAlgorithm string `json:"digestAlgorithm,omitempty"` 25 | 26 | // id 27 | ID string `json:"id,omitempty"` 28 | 29 | // name 30 | Name string `json:"name,omitempty"` 31 | 32 | // size 33 | Size float64 `json:"size,omitempty"` 34 | 35 | // space 36 | Space string `json:"space,omitempty"` 37 | 38 | // namespace 39 | Namespace string `json:"namespace,omitempty"` 40 | } 41 | 42 | /* polymorph FileMetadata digest false */ 43 | 44 | /* polymorph FileMetadata digestAlgorithm false */ 45 | 46 | /* polymorph FileMetadata id false */ 47 | 48 | /* polymorph FileMetadata name false */ 49 | 50 | /* polymorph FileMetadata size false */ 51 | 52 | /* polymorph FileMetadata space false */ 53 | 54 | // Validate validates this file metadata 55 | func (m *FileMetadata) Validate(formats strfmt.Registry) error { 56 | var res []error 57 | 58 | if len(res) > 0 { 59 | return errors.CompositeValidationError(res...) 60 | } 61 | return nil 62 | } 63 | 64 | // MarshalBinary interface implementation 65 | func (m *FileMetadata) MarshalBinary() ([]byte, error) { 66 | if m == nil { 67 | return nil, nil 68 | } 69 | return swag.WriteJSON(m) 70 | } 71 | 72 | // UnmarshalBinary interface implementation 73 | func (m *FileMetadata) UnmarshalBinary(b []byte) error { 74 | var res FileMetadata 75 | if err := swag.ReadJSON(b, &res); err != nil { 76 | return err 77 | } 78 | *m = res 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /clients/models/get_mta_files_o_k_body.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "strconv" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/swag" 15 | ) 16 | 17 | // GetMtaFilesOKBody get mta files o k body 18 | // swagger:model getMtaFilesOKBody 19 | 20 | type GetMtaFilesOKBody []*FileMetadata 21 | 22 | // Validate validates this get mta files o k body 23 | func (m GetMtaFilesOKBody) Validate(formats strfmt.Registry) error { 24 | var res []error 25 | 26 | for i := 0; i < len(m); i++ { 27 | 28 | if swag.IsZero(m[i]) { // not required 29 | continue 30 | } 31 | 32 | if m[i] != nil { 33 | 34 | if err := m[i].Validate(formats); err != nil { 35 | if ve, ok := err.(*errors.Validation); ok { 36 | return ve.ValidateName(strconv.Itoa(i)) 37 | } 38 | return err 39 | } 40 | } 41 | 42 | } 43 | 44 | if len(res) > 0 { 45 | return errors.CompositeValidationError(res...) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /clients/models/get_mta_operation_logs_o_k_body.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "strconv" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/swag" 15 | ) 16 | 17 | // GetMtaOperationLogsOKBody get mta operation logs o k body 18 | // swagger:model getMtaOperationLogsOKBody 19 | 20 | type GetMtaOperationLogsOKBody []*Log 21 | 22 | // Validate validates this get mta operation logs o k body 23 | func (m GetMtaOperationLogsOKBody) Validate(formats strfmt.Registry) error { 24 | var res []error 25 | 26 | for i := 0; i < len(m); i++ { 27 | 28 | if swag.IsZero(m[i]) { // not required 29 | continue 30 | } 31 | 32 | if m[i] != nil { 33 | 34 | if err := m[i].Validate(formats); err != nil { 35 | if ve, ok := err.(*errors.Validation); ok { 36 | return ve.ValidateName(strconv.Itoa(i)) 37 | } 38 | return err 39 | } 40 | } 41 | 42 | } 43 | 44 | if len(res) > 0 { 45 | return errors.CompositeValidationError(res...) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /clients/models/get_mta_operations_o_k_body.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "strconv" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/swag" 15 | ) 16 | 17 | // GetMtaOperationsOKBody get mta operations o k body 18 | // swagger:model getMtaOperationsOKBody 19 | 20 | type GetMtaOperationsOKBody []*Operation 21 | 22 | // Validate validates this get mta operations o k body 23 | func (m GetMtaOperationsOKBody) Validate(formats strfmt.Registry) error { 24 | var res []error 25 | 26 | for i := 0; i < len(m); i++ { 27 | 28 | if swag.IsZero(m[i]) { // not required 29 | continue 30 | } 31 | 32 | if m[i] != nil { 33 | 34 | if err := m[i].Validate(formats); err != nil { 35 | if ve, ok := err.(*errors.Validation); ok { 36 | return ve.ValidateName(strconv.Itoa(i)) 37 | } 38 | return err 39 | } 40 | } 41 | 42 | } 43 | 44 | if len(res) > 0 { 45 | return errors.CompositeValidationError(res...) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /clients/models/get_mtas_o_k_body.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "strconv" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/swag" 15 | ) 16 | 17 | // GetMtasOKBody get mtas o k body 18 | // swagger:model getMtasOKBody 19 | 20 | type GetMtasOKBody []*Mta 21 | 22 | // Validate validates this get mtas o k body 23 | func (m GetMtasOKBody) Validate(formats strfmt.Registry) error { 24 | var res []error 25 | 26 | for i := 0; i < len(m); i++ { 27 | 28 | if swag.IsZero(m[i]) { // not required 29 | continue 30 | } 31 | 32 | if m[i] != nil { 33 | 34 | if err := m[i].Validate(formats); err != nil { 35 | if ve, ok := err.(*errors.Validation); ok { 36 | return ve.ValidateName(strconv.Itoa(i)) 37 | } 38 | return err 39 | } 40 | } 41 | 42 | } 43 | 44 | if len(res) > 0 { 45 | return errors.CompositeValidationError(res...) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /clients/models/http_response_error.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type HttpResponseError struct { 4 | Underlying error 5 | } 6 | 7 | func (e HttpResponseError) Error() string { 8 | return e.Underlying.Error() 9 | } 10 | -------------------------------------------------------------------------------- /clients/models/info.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // Info info 16 | // swagger:model Info 17 | 18 | type Info struct { 19 | 20 | // api version 21 | APIVersion int64 `json:"api_version,omitempty"` 22 | } 23 | 24 | /* polymorph Info api_version false */ 25 | 26 | // Validate validates this info 27 | func (m *Info) Validate(formats strfmt.Registry) error { 28 | var res []error 29 | 30 | if len(res) > 0 { 31 | return errors.CompositeValidationError(res...) 32 | } 33 | return nil 34 | } 35 | 36 | // MarshalBinary interface implementation 37 | func (m *Info) MarshalBinary() ([]byte, error) { 38 | if m == nil { 39 | return nil, nil 40 | } 41 | return swag.WriteJSON(m) 42 | } 43 | 44 | // UnmarshalBinary interface implementation 45 | func (m *Info) UnmarshalBinary(b []byte) error { 46 | var res Info 47 | if err := swag.ReadJSON(b, &res); err != nil { 48 | return err 49 | } 50 | *m = res 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /clients/models/inline_response200.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // InlineResponse200 inline response 200 16 | // swagger:model inline_response_200 17 | 18 | type InlineResponse200 struct { 19 | 20 | // action ids 21 | ActionIds []string `json:"actionIds"` 22 | } 23 | 24 | /* polymorph inline_response_200 actionIds false */ 25 | 26 | // Validate validates this inline response 200 27 | func (m *InlineResponse200) Validate(formats strfmt.Registry) error { 28 | var res []error 29 | 30 | if err := m.validateActionIds(formats); err != nil { 31 | // prop 32 | res = append(res, err) 33 | } 34 | 35 | if len(res) > 0 { 36 | return errors.CompositeValidationError(res...) 37 | } 38 | return nil 39 | } 40 | 41 | func (m *InlineResponse200) validateActionIds(formats strfmt.Registry) error { 42 | 43 | if swag.IsZero(m.ActionIds) { // not required 44 | return nil 45 | } 46 | 47 | return nil 48 | } 49 | 50 | // MarshalBinary interface implementation 51 | func (m *InlineResponse200) MarshalBinary() ([]byte, error) { 52 | if m == nil { 53 | return nil, nil 54 | } 55 | return swag.WriteJSON(m) 56 | } 57 | 58 | // UnmarshalBinary interface implementation 59 | func (m *InlineResponse200) UnmarshalBinary(b []byte) error { 60 | var res InlineResponse200 61 | if err := swag.ReadJSON(b, &res); err != nil { 62 | return err 63 | } 64 | *m = res 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /clients/models/log.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // Log log 16 | // swagger:model Log 17 | 18 | type Log struct { 19 | 20 | // content 21 | Content strfmt.URI `json:"content,omitempty"` 22 | 23 | // description 24 | Description string `json:"description,omitempty"` 25 | 26 | // display name 27 | DisplayName string `json:"displayName,omitempty"` 28 | 29 | // external info 30 | ExternalInfo strfmt.URI `json:"externalInfo,omitempty"` 31 | 32 | // id 33 | ID string `json:"id,omitempty"` 34 | 35 | // last modified 36 | LastModified strfmt.DateTime `json:"lastModified,omitempty"` 37 | 38 | // size 39 | Size int64 `json:"size,omitempty"` 40 | } 41 | 42 | /* polymorph Log content false */ 43 | 44 | /* polymorph Log description false */ 45 | 46 | /* polymorph Log displayName false */ 47 | 48 | /* polymorph Log externalInfo false */ 49 | 50 | /* polymorph Log id false */ 51 | 52 | /* polymorph Log lastModified false */ 53 | 54 | /* polymorph Log size false */ 55 | 56 | // Validate validates this log 57 | func (m *Log) Validate(formats strfmt.Registry) error { 58 | var res []error 59 | 60 | if len(res) > 0 { 61 | return errors.CompositeValidationError(res...) 62 | } 63 | return nil 64 | } 65 | 66 | // MarshalBinary interface implementation 67 | func (m *Log) MarshalBinary() ([]byte, error) { 68 | if m == nil { 69 | return nil, nil 70 | } 71 | return swag.WriteJSON(m) 72 | } 73 | 74 | // UnmarshalBinary interface implementation 75 | func (m *Log) UnmarshalBinary(b []byte) error { 76 | var res Log 77 | if err := swag.ReadJSON(b, &res); err != nil { 78 | return err 79 | } 80 | *m = res 81 | return nil 82 | } 83 | -------------------------------------------------------------------------------- /clients/models/message.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // Message message 16 | // swagger:model Message 17 | 18 | type Message struct { 19 | 20 | // id 21 | ID int64 `json:"id,omitempty"` 22 | 23 | // text 24 | Text string `json:"text,omitempty"` 25 | 26 | // type 27 | Type MessageType `json:"type,omitempty"` 28 | } 29 | 30 | /* polymorph Message id false */ 31 | 32 | /* polymorph Message text false */ 33 | 34 | /* polymorph Message type false */ 35 | 36 | // Validate validates this message 37 | func (m *Message) Validate(formats strfmt.Registry) error { 38 | var res []error 39 | 40 | if err := m.validateType(formats); err != nil { 41 | // prop 42 | res = append(res, err) 43 | } 44 | 45 | if len(res) > 0 { 46 | return errors.CompositeValidationError(res...) 47 | } 48 | return nil 49 | } 50 | 51 | func (m *Message) validateType(formats strfmt.Registry) error { 52 | 53 | if swag.IsZero(m.Type) { // not required 54 | return nil 55 | } 56 | 57 | if err := m.Type.Validate(formats); err != nil { 58 | if ve, ok := err.(*errors.Validation); ok { 59 | return ve.ValidateName("type") 60 | } 61 | return err 62 | } 63 | 64 | return nil 65 | } 66 | 67 | // MarshalBinary interface implementation 68 | func (m *Message) MarshalBinary() ([]byte, error) { 69 | if m == nil { 70 | return nil, nil 71 | } 72 | return swag.WriteJSON(m) 73 | } 74 | 75 | // UnmarshalBinary interface implementation 76 | func (m *Message) UnmarshalBinary(b []byte) error { 77 | var res Message 78 | if err := swag.ReadJSON(b, &res); err != nil { 79 | return err 80 | } 81 | *m = res 82 | return nil 83 | } 84 | -------------------------------------------------------------------------------- /clients/models/message_type.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "encoding/json" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // MessageType message type 18 | // swagger:model MessageType 19 | 20 | type MessageType string 21 | 22 | const ( 23 | // MessageTypeINFO captures enum value "INFO" 24 | MessageTypeINFO MessageType = "INFO" 25 | // MessageTypeERROR captures enum value "ERROR" 26 | MessageTypeERROR MessageType = "ERROR" 27 | // MessageTypeWARNING captures enum value "WARNING" 28 | MessageTypeWARNING MessageType = "WARNING" 29 | // MessageTypeEXT captures enum value "EXT" 30 | MessageTypeEXT MessageType = "EXT" 31 | // MessageTypeTASKSTARTUP captures enum value "TASK_STARTUP" 32 | MessageTypeTASKSTARTUP MessageType = "TASK_STARTUP" 33 | ) 34 | 35 | // for schema 36 | var messageTypeEnum []interface{} 37 | 38 | func init() { 39 | var res []MessageType 40 | if err := json.Unmarshal([]byte(`["INFO","ERROR","WARNING","EXT","TASK_STARTUP"]`), &res); err != nil { 41 | panic(err) 42 | } 43 | for _, v := range res { 44 | messageTypeEnum = append(messageTypeEnum, v) 45 | } 46 | } 47 | 48 | func (m MessageType) validateMessageTypeEnum(path, location string, value MessageType) error { 49 | if err := validate.Enum(path, location, value, messageTypeEnum); err != nil { 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | // Validate validates this message type 56 | func (m MessageType) Validate(formats strfmt.Registry) error { 57 | var res []error 58 | 59 | // value enum 60 | if err := m.validateMessageTypeEnum("", "body", m); err != nil { 61 | return err 62 | } 63 | 64 | if len(res) > 0 { 65 | return errors.CompositeValidationError(res...) 66 | } 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /clients/models/metadata.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/swag" 12 | ) 13 | 14 | // Metadata metadata 15 | // swagger:model Metadata 16 | 17 | type Metadata struct { 18 | 19 | // id 20 | ID string `json:"id,omitempty"` 21 | 22 | // namespace 23 | // Read Only: true 24 | Namespace string `json:"namespace,omitempty"` 25 | 26 | // version 27 | Version string `json:"version,omitempty"` 28 | } 29 | 30 | /* polymorph Metadata id false */ 31 | 32 | /* polymorph Metadata version false */ 33 | 34 | // Validate validates this metadata 35 | func (m *Metadata) Validate(formats strfmt.Registry) error { 36 | return nil 37 | } 38 | 39 | // MarshalBinary interface implementation 40 | func (m *Metadata) MarshalBinary() ([]byte, error) { 41 | if m == nil { 42 | return nil, nil 43 | } 44 | return swag.WriteJSON(m) 45 | } 46 | 47 | // UnmarshalBinary interface implementation 48 | func (m *Metadata) UnmarshalBinary(b []byte) error { 49 | var res Metadata 50 | if err := swag.ReadJSON(b, &res); err != nil { 51 | return err 52 | } 53 | *m = res 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /clients/models/module.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // Module module 16 | // swagger:model Module 17 | 18 | type Module struct { 19 | 20 | // app name 21 | AppName string `json:"appName,omitempty"` 22 | 23 | // created on 24 | CreatedOn strfmt.Date `json:"createdOn,omitempty"` 25 | 26 | // module name 27 | ModuleName string `json:"moduleName,omitempty"` 28 | 29 | // provided dendency names 30 | ProvidedDendencyNames []string `json:"providedDendencyNames"` 31 | 32 | // services 33 | Services []string `json:"services"` 34 | 35 | // updated on 36 | UpdatedOn strfmt.Date `json:"updatedOn,omitempty"` 37 | 38 | // uris 39 | Uris []string `json:"uris"` 40 | } 41 | 42 | /* polymorph Module appName false */ 43 | 44 | /* polymorph Module createdOn false */ 45 | 46 | /* polymorph Module moduleName false */ 47 | 48 | /* polymorph Module providedDendencyNames false */ 49 | 50 | /* polymorph Module services false */ 51 | 52 | /* polymorph Module updatedOn false */ 53 | 54 | /* polymorph Module uris false */ 55 | 56 | // Validate validates this module 57 | func (m *Module) Validate(formats strfmt.Registry) error { 58 | var res []error 59 | 60 | if err := m.validateProvidedDendencyNames(formats); err != nil { 61 | // prop 62 | res = append(res, err) 63 | } 64 | 65 | if err := m.validateServices(formats); err != nil { 66 | // prop 67 | res = append(res, err) 68 | } 69 | 70 | if err := m.validateUris(formats); err != nil { 71 | // prop 72 | res = append(res, err) 73 | } 74 | 75 | if len(res) > 0 { 76 | return errors.CompositeValidationError(res...) 77 | } 78 | return nil 79 | } 80 | 81 | func (m *Module) validateProvidedDendencyNames(formats strfmt.Registry) error { 82 | 83 | if swag.IsZero(m.ProvidedDendencyNames) { // not required 84 | return nil 85 | } 86 | 87 | return nil 88 | } 89 | 90 | func (m *Module) validateServices(formats strfmt.Registry) error { 91 | 92 | if swag.IsZero(m.Services) { // not required 93 | return nil 94 | } 95 | 96 | return nil 97 | } 98 | 99 | func (m *Module) validateUris(formats strfmt.Registry) error { 100 | 101 | if swag.IsZero(m.Uris) { // not required 102 | return nil 103 | } 104 | 105 | return nil 106 | } 107 | 108 | // MarshalBinary interface implementation 109 | func (m *Module) MarshalBinary() ([]byte, error) { 110 | if m == nil { 111 | return nil, nil 112 | } 113 | return swag.WriteJSON(m) 114 | } 115 | 116 | // UnmarshalBinary interface implementation 117 | func (m *Module) UnmarshalBinary(b []byte) error { 118 | var res Module 119 | if err := swag.ReadJSON(b, &res); err != nil { 120 | return err 121 | } 122 | *m = res 123 | return nil 124 | } 125 | -------------------------------------------------------------------------------- /clients/models/mta.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | "github.com/go-openapi/validate" 14 | ) 15 | 16 | // Mta mta 17 | // swagger:model Mta 18 | 19 | type Mta struct { 20 | 21 | // metadata 22 | Metadata *Metadata `json:"metadata,omitempty"` 23 | 24 | // modules 25 | Modules MtaModules `json:"modules"` 26 | 27 | // services 28 | // Unique: true 29 | Services []string `json:"services"` 30 | } 31 | 32 | /* polymorph Mta metadata false */ 33 | 34 | /* polymorph Mta modules false */ 35 | 36 | /* polymorph Mta services false */ 37 | 38 | // Validate validates this mta 39 | func (m *Mta) Validate(formats strfmt.Registry) error { 40 | var res []error 41 | 42 | if err := m.validateMetadata(formats); err != nil { 43 | // prop 44 | res = append(res, err) 45 | } 46 | 47 | if err := m.validateServices(formats); err != nil { 48 | // prop 49 | res = append(res, err) 50 | } 51 | 52 | if len(res) > 0 { 53 | return errors.CompositeValidationError(res...) 54 | } 55 | return nil 56 | } 57 | 58 | func (m *Mta) validateMetadata(formats strfmt.Registry) error { 59 | 60 | if swag.IsZero(m.Metadata) { // not required 61 | return nil 62 | } 63 | 64 | if m.Metadata != nil { 65 | 66 | if err := m.Metadata.Validate(formats); err != nil { 67 | if ve, ok := err.(*errors.Validation); ok { 68 | return ve.ValidateName("metadata") 69 | } 70 | return err 71 | } 72 | } 73 | 74 | return nil 75 | } 76 | 77 | func (m *Mta) validateServices(formats strfmt.Registry) error { 78 | 79 | if swag.IsZero(m.Services) { // not required 80 | return nil 81 | } 82 | 83 | if err := validate.UniqueItems("services", "body", m.Services); err != nil { 84 | return err 85 | } 86 | 87 | return nil 88 | } 89 | 90 | // MarshalBinary interface implementation 91 | func (m *Mta) MarshalBinary() ([]byte, error) { 92 | if m == nil { 93 | return nil, nil 94 | } 95 | return swag.WriteJSON(m) 96 | } 97 | 98 | // UnmarshalBinary interface implementation 99 | func (m *Mta) UnmarshalBinary(b []byte) error { 100 | var res Mta 101 | if err := swag.ReadJSON(b, &res); err != nil { 102 | return err 103 | } 104 | *m = res 105 | return nil 106 | } 107 | -------------------------------------------------------------------------------- /clients/models/mta_modules.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "strconv" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/swag" 15 | ) 16 | 17 | // MtaModules mta modules 18 | // swagger:model mtaModules 19 | 20 | type MtaModules []*Module 21 | 22 | // Validate validates this mta modules 23 | func (m MtaModules) Validate(formats strfmt.Registry) error { 24 | var res []error 25 | 26 | for i := 0; i < len(m); i++ { 27 | 28 | if swag.IsZero(m[i]) { // not required 29 | continue 30 | } 31 | 32 | if m[i] != nil { 33 | 34 | if err := m[i].Validate(formats); err != nil { 35 | if ve, ok := err.(*errors.Validation); ok { 36 | return ve.ValidateName(strconv.Itoa(i)) 37 | } 38 | return err 39 | } 40 | } 41 | 42 | } 43 | 44 | if len(res) > 0 { 45 | return errors.CompositeValidationError(res...) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /clients/models/operation.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | strfmt "github.com/go-openapi/strfmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // Operation operation 16 | // swagger:model Operation 17 | 18 | type Operation struct { 19 | 20 | // acquired lock 21 | AcquiredLock bool `json:"acquiredLock,omitempty"` 22 | 23 | // messages 24 | Messages OperationMessages `json:"messages,omitempty"` 25 | 26 | // mta Id 27 | MtaID string `json:"mtaId,omitempty"` 28 | 29 | // namespace 30 | // Read Only: true 31 | Namespace string `json:"namespace,omitempty"` 32 | 33 | // parameters 34 | Parameters map[string]interface{} `json:"parameters,omitempty"` 35 | 36 | // process Id 37 | ProcessID string `json:"processId,omitempty"` 38 | 39 | // process type 40 | ProcessType string `json:"processType,omitempty"` 41 | 42 | // space Id 43 | SpaceID string `json:"spaceId,omitempty"` 44 | 45 | // started at 46 | StartedAt string `json:"startedAt,omitempty"` 47 | 48 | // state 49 | State State `json:"state,omitempty"` 50 | 51 | // error type 52 | ErrorType ErrorType `json:"errorType,omitempty"` 53 | 54 | // user 55 | User string `json:"user,omitempty"` 56 | } 57 | 58 | /* polymorph Operation acquiredLock false */ 59 | 60 | /* polymorph Operation messages false */ 61 | 62 | /* polymorph Operation mtaId false */ 63 | 64 | /* polymorph Operation parameters false */ 65 | 66 | /* polymorph Operation processId false */ 67 | 68 | /* polymorph Operation processType false */ 69 | 70 | /* polymorph Operation spaceId false */ 71 | 72 | /* polymorph Operation startedAt false */ 73 | 74 | /* polymorph Operation state false */ 75 | 76 | /* polymorph Operation errorType false */ 77 | 78 | /* polymorph Operation user false */ 79 | 80 | // Validate validates this operation 81 | func (m *Operation) Validate(formats strfmt.Registry) error { 82 | var res []error 83 | 84 | if err := m.validateState(formats); err != nil { 85 | // prop 86 | res = append(res, err) 87 | } 88 | 89 | if err := m.validateErrorType(formats); err != nil { 90 | res = append(res, err) 91 | } 92 | 93 | if len(res) > 0 { 94 | return errors.CompositeValidationError(res...) 95 | } 96 | return nil 97 | } 98 | 99 | func (m *Operation) validateState(formats strfmt.Registry) error { 100 | 101 | if swag.IsZero(m.State) { // not required 102 | return nil 103 | } 104 | 105 | if err := m.State.Validate(formats); err != nil { 106 | if ve, ok := err.(*errors.Validation); ok { 107 | return ve.ValidateName("state") 108 | } 109 | return err 110 | } 111 | 112 | return nil 113 | } 114 | 115 | func (m *Operation) validateErrorType(formats strfmt.Registry) error { 116 | if swag.IsZero(m.ErrorType) { 117 | return nil 118 | } 119 | 120 | if err := m.ErrorType.Validate(formats); err != nil { 121 | if ve, ok := err.(*errors.Validation); ok { 122 | return ve.ValidateName("errorType") 123 | } 124 | return nil 125 | } 126 | return nil 127 | } 128 | 129 | // MarshalBinary interface implementation 130 | func (m *Operation) MarshalBinary() ([]byte, error) { 131 | if m == nil { 132 | return nil, nil 133 | } 134 | return swag.WriteJSON(m) 135 | } 136 | 137 | // UnmarshalBinary interface implementation 138 | func (m *Operation) UnmarshalBinary(b []byte) error { 139 | var res Operation 140 | if err := swag.ReadJSON(b, &res); err != nil { 141 | return err 142 | } 143 | *m = res 144 | return nil 145 | } 146 | -------------------------------------------------------------------------------- /clients/models/operation_messages.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "strconv" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/swag" 15 | ) 16 | 17 | // OperationMessages operation messages 18 | // swagger:model operationMessages 19 | 20 | type OperationMessages []*Message 21 | 22 | // Validate validates this operation messages 23 | func (m OperationMessages) Validate(formats strfmt.Registry) error { 24 | var res []error 25 | 26 | for i := 0; i < len(m); i++ { 27 | 28 | if swag.IsZero(m[i]) { // not required 29 | continue 30 | } 31 | 32 | if m[i] != nil { 33 | 34 | if err := m[i].Validate(formats); err != nil { 35 | if ve, ok := err.(*errors.Validation); ok { 36 | return ve.ValidateName(strconv.Itoa(i)) 37 | } 38 | return err 39 | } 40 | } 41 | 42 | } 43 | 44 | if len(res) > 0 { 45 | return errors.CompositeValidationError(res...) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /clients/models/paginated_response.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type PaginatedResponse[T any] struct { 4 | Pagination Pagination `json:"pagination"` 5 | Resources []T `json:"resources"` 6 | } 7 | 8 | type Pagination struct { 9 | TotalPages int64 `json:"total_pages"` 10 | NextPage string `jsonry:"next.href"` 11 | } 12 | 13 | type PaginatedResponseWithIncluded[T any, Included any] struct { 14 | Pagination Pagination `json:"pagination"` 15 | Resources []T `json:"resources"` 16 | Included Included `json:"included"` 17 | } 18 | -------------------------------------------------------------------------------- /clients/models/state.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "encoding/json" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | 13 | "github.com/go-openapi/errors" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // State state 18 | // swagger:model State 19 | 20 | type State string 21 | 22 | const ( 23 | // StateRUNNING captures enum value "RUNNING" 24 | StateRUNNING State = "RUNNING" 25 | // StateFINISHED captures enum value "FINISHED" 26 | StateFINISHED State = "FINISHED" 27 | // StateERROR captures enum value "ERROR" 28 | StateERROR State = "ERROR" 29 | // StateABORTED captures enum value "ABORTED" 30 | StateABORTED State = "ABORTED" 31 | // StateACTIONREQUIRED captures enum value "ACTION_REQUIRED" 32 | StateACTIONREQUIRED State = "ACTION_REQUIRED" 33 | ) 34 | 35 | // for schema 36 | var stateEnum []interface{} 37 | 38 | func init() { 39 | var res []State 40 | if err := json.Unmarshal([]byte(`["RUNNING","FINISHED","ERROR","ABORTED","ACTION_REQUIRED"]`), &res); err != nil { 41 | panic(err) 42 | } 43 | for _, v := range res { 44 | stateEnum = append(stateEnum, v) 45 | } 46 | } 47 | 48 | func (m State) validateStateEnum(path, location string, value State) error { 49 | if err := validate.Enum(path, location, value, stateEnum); err != nil { 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | // Validate validates this state 56 | func (m State) Validate(formats strfmt.Registry) error { 57 | var res []error 58 | 59 | // value enum 60 | if err := m.validateStateEnum("", "body", m); err != nil { 61 | return err 62 | } 63 | 64 | if len(res) > 0 { 65 | return errors.CompositeValidationError(res...) 66 | } 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /clients/mtaclient/fakes/fake_mta_client_builder.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient" 9 | ) 10 | 11 | type FakeMtaClientBuilder struct { 12 | FakeMtaClient *FakeMtaClientOperations 13 | } 14 | 15 | func NewFakeMtaClientBuilder() *FakeMtaClientBuilder { 16 | return &FakeMtaClientBuilder{&FakeMtaClientOperations{}} 17 | } 18 | 19 | func (fb *FakeMtaClientBuilder) ExecuteAction(operationID, actionID string, resultHeader mtaclient.ResponseHeader, resultError error) *FakeMtaClientBuilder { 20 | fb.FakeMtaClient.ExecuteActionReturns(resultHeader, resultError) 21 | return fb 22 | } 23 | func (fb *FakeMtaClientBuilder) GetMta(mtaID string, resultMta *models.Mta, resultError error) *FakeMtaClientBuilder { 24 | fb.FakeMtaClient.GetMtaReturns(resultMta, resultError) 25 | return fb 26 | } 27 | func (fb *FakeMtaClientBuilder) GetMtaFiles(result []*models.FileMetadata, resultError error) *FakeMtaClientBuilder { 28 | fb.FakeMtaClient.GetMtaFilesReturns(result, resultError) 29 | return fb 30 | } 31 | func (fb *FakeMtaClientBuilder) GetMtaOperation(operaWtionID, embed string, result *models.Operation, resultErr error) *FakeMtaClientBuilder { 32 | fb.FakeMtaClient.GetMtaOperationReturns(result, resultErr) 33 | return fb 34 | } 35 | func (fb *FakeMtaClientBuilder) GetMtaOperationLogs(operationID string, result []*models.Log, resultErr error) *FakeMtaClientBuilder { 36 | fb.FakeMtaClient.GetMtaOperationLogsReturns(result, resultErr) 37 | return fb 38 | } 39 | func (fb *FakeMtaClientBuilder) GetMtaOperations(mtaId *string, last *int64, status []string, result []*models.Operation, resultErr error) *FakeMtaClientBuilder { 40 | fb.FakeMtaClient.GetMtaOperationsReturns(result, resultErr) 41 | return fb 42 | } 43 | func (fb *FakeMtaClientBuilder) GetMtas(result []*models.Mta, resultErr error) *FakeMtaClientBuilder { 44 | fb.FakeMtaClient.GetMtasReturns(result, resultErr) 45 | return fb 46 | } 47 | func (fb *FakeMtaClientBuilder) GetOperationActions(operationID string, result []string, resultErr error) *FakeMtaClientBuilder { 48 | fb.FakeMtaClient.GetOperationActionsReturns(result, resultErr) 49 | return fb 50 | } 51 | func (fb *FakeMtaClientBuilder) StartMtaOperation(operation models.Operation, result mtaclient.ResponseHeader, resultError error) *FakeMtaClientBuilder { 52 | fb.FakeMtaClient.StartMtaOperationReturns(result, resultError) 53 | return fb 54 | } 55 | func (fb *FakeMtaClientBuilder) UploadMtaFile(file *os.File, result *models.FileMetadata, resultError error) *FakeMtaClientBuilder { 56 | fb.FakeMtaClient.UploadMtaFileReturns(result, resultError) 57 | return fb 58 | } 59 | func (fb *FakeMtaClientBuilder) StartUploadMtaArchiveFromUrl(fileUrl string, namespace *string, result http.Header, resultError error) *FakeMtaClientBuilder { 60 | fb.FakeMtaClient.StartUploadMtaArchiveFromUrlReturnsOnCall(fileUrl, namespace, result, resultError) 61 | return fb 62 | } 63 | func (fb *FakeMtaClientBuilder) GetAsyncUploadJob(jobId string, namespace *string, appInstanceId string, result mtaclient.AsyncUploadJobResult, resultErr error) *FakeMtaClientBuilder { 64 | fb.FakeMtaClient.GetAsyncUploadJobReturnsOnCall(jobId, namespace, appInstanceId, result, resultErr) 65 | return fb 66 | } 67 | func (fb *FakeMtaClientBuilder) GetMtaOperationLogContent(operationID, logID string, result string, resultError error) *FakeMtaClientBuilder { 68 | fb.FakeMtaClient.GetMtaOperationLogContentReturns(result, resultError) 69 | return fb 70 | } 71 | 72 | func (fb *FakeMtaClientBuilder) Build() *FakeMtaClientOperations { 73 | return fb.FakeMtaClient 74 | } 75 | -------------------------------------------------------------------------------- /clients/mtaclient/mta_client_operations.go: -------------------------------------------------------------------------------- 1 | package mtaclient 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 6 | "github.com/go-openapi/strfmt" 7 | "net/http" 8 | ) 9 | 10 | // MtaClientOperations drun drun drun 11 | type MtaClientOperations interface { 12 | ExecuteAction(operationID, actionID string) (ResponseHeader, error) 13 | GetMta(mtaID string) (*models.Mta, error) 14 | GetMtaFiles(namespace *string) ([]*models.FileMetadata, error) 15 | GetMtaOperation(operationID, embed string) (*models.Operation, error) 16 | GetMtaOperationLogs(operationID string) ([]*models.Log, error) 17 | GetMtaOperations(mtaId *string, last *int64, status []string) ([]*models.Operation, error) 18 | GetMtas() ([]*models.Mta, error) 19 | GetOperationActions(operationID string) ([]string, error) 20 | StartMtaOperation(operation models.Operation) (ResponseHeader, error) 21 | UploadMtaFile(file util.NamedReadSeeker, fileSize int64, namespace *string) (*models.FileMetadata, error) 22 | StartUploadMtaArchiveFromUrl(fileUrl string, namespace *string) (http.Header, error) 23 | GetAsyncUploadJob(jobId string, namespace *string, appInstanceId string) (AsyncUploadJobResult, error) 24 | GetMtaOperationLogContent(operationID, logID string) (string, error) 25 | } 26 | 27 | // ResponseHeader response header 28 | type ResponseHeader struct { 29 | Location strfmt.URI 30 | } 31 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/execute_operation_action_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | ) 18 | 19 | // ExecuteOperationActionReader is a Reader for the ExecuteOperationAction structure. 20 | type ExecuteOperationActionReader struct { 21 | formats strfmt.Registry 22 | } 23 | 24 | // ReadResponse reads a server response into the received o. 25 | func (o *ExecuteOperationActionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 26 | switch response.Code() { 27 | 28 | case 202: 29 | result := NewExecuteOperationActionAccepted() 30 | if err := result.readResponse(response, consumer, o.formats); err != nil { 31 | return nil, err 32 | } 33 | return result, nil 34 | 35 | default: 36 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 37 | } 38 | } 39 | 40 | // NewExecuteOperationActionAccepted creates a ExecuteOperationActionAccepted with default headers values 41 | func NewExecuteOperationActionAccepted() *ExecuteOperationActionAccepted { 42 | return &ExecuteOperationActionAccepted{} 43 | } 44 | 45 | /*ExecuteOperationActionAccepted handles this case with default header values. 46 | 47 | Accepted 48 | */ 49 | type ExecuteOperationActionAccepted struct { 50 | Location strfmt.URI 51 | } 52 | 53 | func (o *ExecuteOperationActionAccepted) Error() string { 54 | return fmt.Sprintf("[POST /operations/{operationId}][%d] executeOperationActionAccepted ", 202) 55 | } 56 | 57 | func (o *ExecuteOperationActionAccepted) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 58 | 59 | // response header Location 60 | 61 | location, err := formats.Parse("uri", response.GetHeader("Location")) 62 | if err != nil { 63 | return errors.InvalidType("Location", "header", "strfmt.URI", response.GetHeader("Location")) 64 | } 65 | o.Location = *(location.(*strfmt.URI)) 66 | 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_csrf_token_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | "time" 11 | 12 | "golang.org/x/net/context" 13 | 14 | "github.com/go-openapi/errors" 15 | "github.com/go-openapi/runtime" 16 | cr "github.com/go-openapi/runtime/client" 17 | 18 | strfmt "github.com/go-openapi/strfmt" 19 | ) 20 | 21 | // NewGetCsrfTokenParams creates a new GetCsrfTokenParams object 22 | // with the default values initialized. 23 | func NewGetCsrfTokenParams() *GetCsrfTokenParams { 24 | 25 | return &GetCsrfTokenParams{ 26 | 27 | timeout: cr.DefaultTimeout, 28 | } 29 | } 30 | 31 | // NewGetCsrfTokenParamsWithTimeout creates a new GetCsrfTokenParams object 32 | // with the default values initialized, and the ability to set a timeout on a request 33 | func NewGetCsrfTokenParamsWithTimeout(timeout time.Duration) *GetCsrfTokenParams { 34 | 35 | return &GetCsrfTokenParams{ 36 | 37 | timeout: timeout, 38 | } 39 | } 40 | 41 | // NewGetCsrfTokenParamsWithContext creates a new GetCsrfTokenParams object 42 | // with the default values initialized, and the ability to set a context for a request 43 | func NewGetCsrfTokenParamsWithContext(ctx context.Context) *GetCsrfTokenParams { 44 | 45 | return &GetCsrfTokenParams{ 46 | 47 | Context: ctx, 48 | } 49 | } 50 | 51 | // NewGetCsrfTokenParamsWithHTTPClient creates a new GetCsrfTokenParams object 52 | // with the default values initialized, and the ability to set a custom HTTPClient for a request 53 | func NewGetCsrfTokenParamsWithHTTPClient(client *http.Client) *GetCsrfTokenParams { 54 | 55 | return &GetCsrfTokenParams{ 56 | HTTPClient: client, 57 | } 58 | } 59 | 60 | /*GetCsrfTokenParams contains all the parameters to send to the API endpoint 61 | for the get csrf token operation typically these are written to a http.Request 62 | */ 63 | type GetCsrfTokenParams struct { 64 | timeout time.Duration 65 | Context context.Context 66 | HTTPClient *http.Client 67 | } 68 | 69 | // WithTimeout adds the timeout to the get csrf token params 70 | func (o *GetCsrfTokenParams) WithTimeout(timeout time.Duration) *GetCsrfTokenParams { 71 | o.SetTimeout(timeout) 72 | return o 73 | } 74 | 75 | // SetTimeout adds the timeout to the get csrf token params 76 | func (o *GetCsrfTokenParams) SetTimeout(timeout time.Duration) { 77 | o.timeout = timeout 78 | } 79 | 80 | // WithContext adds the context to the get csrf token params 81 | func (o *GetCsrfTokenParams) WithContext(ctx context.Context) *GetCsrfTokenParams { 82 | o.SetContext(ctx) 83 | return o 84 | } 85 | 86 | // SetContext adds the context to the get csrf token params 87 | func (o *GetCsrfTokenParams) SetContext(ctx context.Context) { 88 | o.Context = ctx 89 | } 90 | 91 | // WithHTTPClient adds the HTTPClient to the get csrf token params 92 | func (o *GetCsrfTokenParams) WithHTTPClient(client *http.Client) *GetCsrfTokenParams { 93 | o.SetHTTPClient(client) 94 | return o 95 | } 96 | 97 | // SetHTTPClient adds the HTTPClient to the get csrf token params 98 | func (o *GetCsrfTokenParams) SetHTTPClient(client *http.Client) { 99 | o.HTTPClient = client 100 | } 101 | 102 | // WriteToRequest writes these params to a swagger request 103 | func (o *GetCsrfTokenParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { 104 | 105 | if err := r.SetTimeout(o.timeout); err != nil { 106 | return err 107 | } 108 | var res []error 109 | 110 | if len(res) > 0 { 111 | return errors.CompositeValidationError(res...) 112 | } 113 | return nil 114 | } 115 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_csrf_token_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/runtime" 12 | 13 | strfmt "github.com/go-openapi/strfmt" 14 | 15 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 16 | ) 17 | 18 | // GetCsrfTokenReader is a Reader for the GetCsrfToken structure. 19 | type GetCsrfTokenReader struct { 20 | formats strfmt.Registry 21 | } 22 | 23 | // ReadResponse reads a server response into the received o. 24 | func (o *GetCsrfTokenReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 25 | switch response.Code() { 26 | 27 | case 204: 28 | result := NewGetCsrfTokenNoContent() 29 | if err := result.readResponse(response, consumer, o.formats); err != nil { 30 | return nil, err 31 | } 32 | return result, nil 33 | 34 | default: 35 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 36 | } 37 | } 38 | 39 | // NewGetCsrfTokenNoContent creates a GetCsrfTokenNoContent with default headers values 40 | func NewGetCsrfTokenNoContent() *GetCsrfTokenNoContent { 41 | return &GetCsrfTokenNoContent{} 42 | } 43 | 44 | /*GetCsrfTokenNoContent handles this case with default header values. 45 | 46 | No Content 47 | */ 48 | type GetCsrfTokenNoContent struct { 49 | } 50 | 51 | func (o *GetCsrfTokenNoContent) Error() string { 52 | return fmt.Sprintf("[GET /csrf-token][%d] getCsrfTokenNoContent ", 204) 53 | } 54 | 55 | func (o *GetCsrfTokenNoContent) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 56 | 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_info_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | "time" 11 | 12 | "golang.org/x/net/context" 13 | 14 | "github.com/go-openapi/errors" 15 | "github.com/go-openapi/runtime" 16 | cr "github.com/go-openapi/runtime/client" 17 | 18 | strfmt "github.com/go-openapi/strfmt" 19 | ) 20 | 21 | // NewGetInfoParams creates a new GetInfoParams object 22 | // with the default values initialized. 23 | func NewGetInfoParams() *GetInfoParams { 24 | 25 | return &GetInfoParams{ 26 | 27 | timeout: cr.DefaultTimeout, 28 | } 29 | } 30 | 31 | // NewGetInfoParamsWithTimeout creates a new GetInfoParams object 32 | // with the default values initialized, and the ability to set a timeout on a request 33 | func NewGetInfoParamsWithTimeout(timeout time.Duration) *GetInfoParams { 34 | 35 | return &GetInfoParams{ 36 | 37 | timeout: timeout, 38 | } 39 | } 40 | 41 | // NewGetInfoParamsWithContext creates a new GetInfoParams object 42 | // with the default values initialized, and the ability to set a context for a request 43 | func NewGetInfoParamsWithContext(ctx context.Context) *GetInfoParams { 44 | 45 | return &GetInfoParams{ 46 | 47 | Context: ctx, 48 | } 49 | } 50 | 51 | // NewGetInfoParamsWithHTTPClient creates a new GetInfoParams object 52 | // with the default values initialized, and the ability to set a custom HTTPClient for a request 53 | func NewGetInfoParamsWithHTTPClient(client *http.Client) *GetInfoParams { 54 | 55 | return &GetInfoParams{ 56 | HTTPClient: client, 57 | } 58 | } 59 | 60 | /*GetInfoParams contains all the parameters to send to the API endpoint 61 | for the get info operation typically these are written to a http.Request 62 | */ 63 | type GetInfoParams struct { 64 | timeout time.Duration 65 | Context context.Context 66 | HTTPClient *http.Client 67 | } 68 | 69 | // WithTimeout adds the timeout to the get info params 70 | func (o *GetInfoParams) WithTimeout(timeout time.Duration) *GetInfoParams { 71 | o.SetTimeout(timeout) 72 | return o 73 | } 74 | 75 | // SetTimeout adds the timeout to the get info params 76 | func (o *GetInfoParams) SetTimeout(timeout time.Duration) { 77 | o.timeout = timeout 78 | } 79 | 80 | // WithContext adds the context to the get info params 81 | func (o *GetInfoParams) WithContext(ctx context.Context) *GetInfoParams { 82 | o.SetContext(ctx) 83 | return o 84 | } 85 | 86 | // SetContext adds the context to the get info params 87 | func (o *GetInfoParams) SetContext(ctx context.Context) { 88 | o.Context = ctx 89 | } 90 | 91 | // WithHTTPClient adds the HTTPClient to the get info params 92 | func (o *GetInfoParams) WithHTTPClient(client *http.Client) *GetInfoParams { 93 | o.SetHTTPClient(client) 94 | return o 95 | } 96 | 97 | // SetHTTPClient adds the HTTPClient to the get info params 98 | func (o *GetInfoParams) SetHTTPClient(client *http.Client) { 99 | o.HTTPClient = client 100 | } 101 | 102 | // WriteToRequest writes these params to a swagger request 103 | func (o *GetInfoParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { 104 | 105 | if err := r.SetTimeout(o.timeout); err != nil { 106 | return err 107 | } 108 | var res []error 109 | 110 | if len(res) > 0 { 111 | return errors.CompositeValidationError(res...) 112 | } 113 | return nil 114 | } 115 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_info_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetInfoReader is a Reader for the GetInfo structure. 21 | type GetInfoReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetInfoReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetInfoOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetInfoOK creates a GetInfoOK with default headers values 42 | func NewGetInfoOK() *GetInfoOK { 43 | return &GetInfoOK{} 44 | } 45 | 46 | /*GetInfoOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetInfoOK struct { 51 | Payload *models.Info 52 | } 53 | 54 | func (o *GetInfoOK) Error() string { 55 | return fmt.Sprintf("[GET /info][%d] getInfoOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetInfoOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | o.Payload = new(models.Info) 61 | 62 | // response payload 63 | if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mta_files_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtaFilesReader is a Reader for the GetMtaFiles structure. 21 | type GetMtaFilesReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtaFilesReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetMtaFilesOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetMtaFilesOK creates a GetMtaFilesOK with default headers values 42 | func NewGetMtaFilesOK() *GetMtaFilesOK { 43 | return &GetMtaFilesOK{} 44 | } 45 | 46 | /*GetMtaFilesOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetMtaFilesOK struct { 51 | Payload models.GetMtaFilesOKBody 52 | } 53 | 54 | func (o *GetMtaFilesOK) Error() string { 55 | return fmt.Sprintf("[GET /files][%d] getMtaFilesOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetMtaFilesOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | // response payload 61 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 62 | return err 63 | } 64 | 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mta_operation_log_content_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | ) 18 | 19 | // GetMtaOperationLogContentReader is a Reader for the GetMtaOperationLogContent structure. 20 | type GetMtaOperationLogContentReader struct { 21 | formats strfmt.Registry 22 | } 23 | 24 | // ReadResponse reads a server response into the received o. 25 | func (o *GetMtaOperationLogContentReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 26 | switch response.Code() { 27 | 28 | case 200: 29 | result := NewGetMtaOperationLogContentOK() 30 | if err := result.readResponse(response, consumer, o.formats); err != nil { 31 | return nil, err 32 | } 33 | return result, nil 34 | 35 | default: 36 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 37 | } 38 | } 39 | 40 | // NewGetMtaOperationLogContentOK creates a GetMtaOperationLogContentOK with default headers values 41 | func NewGetMtaOperationLogContentOK() *GetMtaOperationLogContentOK { 42 | return &GetMtaOperationLogContentOK{} 43 | } 44 | 45 | /*GetMtaOperationLogContentOK handles this case with default header values. 46 | 47 | OK 48 | */ 49 | type GetMtaOperationLogContentOK struct { 50 | Payload string 51 | } 52 | 53 | func (o *GetMtaOperationLogContentOK) Error() string { 54 | return fmt.Sprintf("[GET /operations/{operationId}/logs/{logId}/content][%d] getMtaOperationLogContentOK %+v", 200, o.Payload) 55 | } 56 | 57 | func (o *GetMtaOperationLogContentOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 58 | 59 | // response payload 60 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 61 | return err 62 | } 63 | 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mta_operation_logs_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtaOperationLogsReader is a Reader for the GetMtaOperationLogs structure. 21 | type GetMtaOperationLogsReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtaOperationLogsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetMtaOperationLogsOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetMtaOperationLogsOK creates a GetMtaOperationLogsOK with default headers values 42 | func NewGetMtaOperationLogsOK() *GetMtaOperationLogsOK { 43 | return &GetMtaOperationLogsOK{} 44 | } 45 | 46 | /*GetMtaOperationLogsOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetMtaOperationLogsOK struct { 51 | Payload models.GetMtaOperationLogsOKBody 52 | } 53 | 54 | func (o *GetMtaOperationLogsOK) Error() string { 55 | return fmt.Sprintf("[GET /operations/{operationId}/logs][%d] getMtaOperationLogsOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetMtaOperationLogsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | // response payload 61 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 62 | return err 63 | } 64 | 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mta_operation_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtaOperationReader is a Reader for the GetMtaOperation structure. 21 | type GetMtaOperationReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtaOperationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetMtaOperationOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetMtaOperationOK creates a GetMtaOperationOK with default headers values 42 | func NewGetMtaOperationOK() *GetMtaOperationOK { 43 | return &GetMtaOperationOK{} 44 | } 45 | 46 | /*GetMtaOperationOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetMtaOperationOK struct { 51 | Payload *models.Operation 52 | } 53 | 54 | func (o *GetMtaOperationOK) Error() string { 55 | return fmt.Sprintf("[GET /operations/{operationId}][%d] getMtaOperationOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetMtaOperationOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | o.Payload = new(models.Operation) 61 | 62 | // response payload 63 | if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mta_operations_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtaOperationsReader is a Reader for the GetMtaOperations structure. 21 | type GetMtaOperationsReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtaOperationsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetMtaOperationsOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetMtaOperationsOK creates a GetMtaOperationsOK with default headers values 42 | func NewGetMtaOperationsOK() *GetMtaOperationsOK { 43 | return &GetMtaOperationsOK{} 44 | } 45 | 46 | /*GetMtaOperationsOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetMtaOperationsOK struct { 51 | Payload models.GetMtaOperationsOKBody 52 | } 53 | 54 | func (o *GetMtaOperationsOK) Error() string { 55 | return fmt.Sprintf("[GET /operations][%d] getMtaOperationsOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetMtaOperationsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | // response payload 61 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 62 | return err 63 | } 64 | 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mta_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtaReader is a Reader for the GetMta structure. 21 | type GetMtaReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtaReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetMtaOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetMtaOK creates a GetMtaOK with default headers values 42 | func NewGetMtaOK() *GetMtaOK { 43 | return &GetMtaOK{} 44 | } 45 | 46 | /*GetMtaOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetMtaOK struct { 51 | Payload *models.Mta 52 | } 53 | 54 | func (o *GetMtaOK) Error() string { 55 | return fmt.Sprintf("[GET /mtas/{mta_id}][%d] getMtaOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetMtaOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | o.Payload = new(models.Mta) 61 | 62 | // response payload 63 | if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mtas_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | "time" 11 | 12 | "golang.org/x/net/context" 13 | 14 | "github.com/go-openapi/errors" 15 | "github.com/go-openapi/runtime" 16 | cr "github.com/go-openapi/runtime/client" 17 | 18 | strfmt "github.com/go-openapi/strfmt" 19 | ) 20 | 21 | // NewGetMtasParams creates a new GetMtasParams object 22 | // with the default values initialized. 23 | func NewGetMtasParams() *GetMtasParams { 24 | 25 | return &GetMtasParams{ 26 | 27 | timeout: cr.DefaultTimeout, 28 | } 29 | } 30 | 31 | // NewGetMtasParamsWithTimeout creates a new GetMtasParams object 32 | // with the default values initialized, and the ability to set a timeout on a request 33 | func NewGetMtasParamsWithTimeout(timeout time.Duration) *GetMtasParams { 34 | 35 | return &GetMtasParams{ 36 | 37 | timeout: timeout, 38 | } 39 | } 40 | 41 | // NewGetMtasParamsWithContext creates a new GetMtasParams object 42 | // with the default values initialized, and the ability to set a context for a request 43 | func NewGetMtasParamsWithContext(ctx context.Context) *GetMtasParams { 44 | 45 | return &GetMtasParams{ 46 | 47 | Context: ctx, 48 | } 49 | } 50 | 51 | // NewGetMtasParamsWithHTTPClient creates a new GetMtasParams object 52 | // with the default values initialized, and the ability to set a custom HTTPClient for a request 53 | func NewGetMtasParamsWithHTTPClient(client *http.Client) *GetMtasParams { 54 | 55 | return &GetMtasParams{ 56 | HTTPClient: client, 57 | } 58 | } 59 | 60 | /*GetMtasParams contains all the parameters to send to the API endpoint 61 | for the get mtas operation typically these are written to a http.Request 62 | */ 63 | type GetMtasParams struct { 64 | timeout time.Duration 65 | Context context.Context 66 | HTTPClient *http.Client 67 | } 68 | 69 | // WithTimeout adds the timeout to the get mtas params 70 | func (o *GetMtasParams) WithTimeout(timeout time.Duration) *GetMtasParams { 71 | o.SetTimeout(timeout) 72 | return o 73 | } 74 | 75 | // SetTimeout adds the timeout to the get mtas params 76 | func (o *GetMtasParams) SetTimeout(timeout time.Duration) { 77 | o.timeout = timeout 78 | } 79 | 80 | // WithContext adds the context to the get mtas params 81 | func (o *GetMtasParams) WithContext(ctx context.Context) *GetMtasParams { 82 | o.SetContext(ctx) 83 | return o 84 | } 85 | 86 | // SetContext adds the context to the get mtas params 87 | func (o *GetMtasParams) SetContext(ctx context.Context) { 88 | o.Context = ctx 89 | } 90 | 91 | // WithHTTPClient adds the HTTPClient to the get mtas params 92 | func (o *GetMtasParams) WithHTTPClient(client *http.Client) *GetMtasParams { 93 | o.SetHTTPClient(client) 94 | return o 95 | } 96 | 97 | // SetHTTPClient adds the HTTPClient to the get mtas params 98 | func (o *GetMtasParams) SetHTTPClient(client *http.Client) { 99 | o.HTTPClient = client 100 | } 101 | 102 | // WriteToRequest writes these params to a swagger request 103 | func (o *GetMtasParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { 104 | 105 | if err := r.SetTimeout(o.timeout); err != nil { 106 | return err 107 | } 108 | var res []error 109 | 110 | if len(res) > 0 { 111 | return errors.CompositeValidationError(res...) 112 | } 113 | return nil 114 | } 115 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_mtas_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtasReader is a Reader for the GetMtas structure. 21 | type GetMtasReader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtasReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | 29 | case 200: 30 | result := NewGetMtasOK() 31 | if err := result.readResponse(response, consumer, o.formats); err != nil { 32 | return nil, err 33 | } 34 | return result, nil 35 | 36 | default: 37 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 38 | } 39 | } 40 | 41 | // NewGetMtasOK creates a GetMtasOK with default headers values 42 | func NewGetMtasOK() *GetMtasOK { 43 | return &GetMtasOK{} 44 | } 45 | 46 | /*GetMtasOK handles this case with default header values. 47 | 48 | OK 49 | */ 50 | type GetMtasOK struct { 51 | Payload models.GetMtasOKBody 52 | } 53 | 54 | func (o *GetMtasOK) Error() string { 55 | return fmt.Sprintf("[GET /mtas][%d] getMtasOK %+v", 200, o.Payload) 56 | } 57 | 58 | func (o *GetMtasOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 59 | 60 | // response payload 61 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 62 | return err 63 | } 64 | 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/get_operation_actions_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | ) 18 | 19 | // GetOperationActionsReader is a Reader for the GetOperationActions structure. 20 | type GetOperationActionsReader struct { 21 | formats strfmt.Registry 22 | } 23 | 24 | // ReadResponse reads a server response into the received o. 25 | func (o *GetOperationActionsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 26 | switch response.Code() { 27 | 28 | case 200: 29 | result := NewGetOperationActionsOK() 30 | if err := result.readResponse(response, consumer, o.formats); err != nil { 31 | return nil, err 32 | } 33 | return result, nil 34 | 35 | default: 36 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 37 | } 38 | } 39 | 40 | // NewGetOperationActionsOK creates a GetOperationActionsOK with default headers values 41 | func NewGetOperationActionsOK() *GetOperationActionsOK { 42 | return &GetOperationActionsOK{} 43 | } 44 | 45 | /*GetOperationActionsOK handles this case with default header values. 46 | 47 | OK 48 | */ 49 | type GetOperationActionsOK struct { 50 | Payload []string 51 | } 52 | 53 | func (o *GetOperationActionsOK) Error() string { 54 | return fmt.Sprintf("[GET /operations/{operationId}/actions][%d] getOperationActionsOK %+v", 200, o.Payload) 55 | } 56 | 57 | func (o *GetOperationActionsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 58 | 59 | // response payload 60 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 61 | return err 62 | } 63 | 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /clients/mtaclient/operations/start_mta_operation_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | ) 18 | 19 | // StartMtaOperationReader is a Reader for the StartMtaOperation structure. 20 | type StartMtaOperationReader struct { 21 | formats strfmt.Registry 22 | } 23 | 24 | // ReadResponse reads a server response into the received o. 25 | func (o *StartMtaOperationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 26 | switch response.Code() { 27 | 28 | case 202: 29 | result := NewStartMtaOperationAccepted() 30 | if err := result.readResponse(response, consumer, o.formats); err != nil { 31 | return nil, err 32 | } 33 | return result, nil 34 | 35 | default: 36 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 37 | } 38 | } 39 | 40 | // NewStartMtaOperationAccepted creates a StartMtaOperationAccepted with default headers values 41 | func NewStartMtaOperationAccepted() *StartMtaOperationAccepted { 42 | return &StartMtaOperationAccepted{} 43 | } 44 | 45 | /*StartMtaOperationAccepted handles this case with default header values. 46 | 47 | Accepted 48 | */ 49 | type StartMtaOperationAccepted struct { 50 | /*A Location header, used for transpassing between different resources 51 | 52 | */ 53 | Location strfmt.URI 54 | } 55 | 56 | func (o *StartMtaOperationAccepted) Error() string { 57 | return fmt.Sprintf("[POST /operations][%d] startMtaOperationAccepted ", 202) 58 | } 59 | 60 | func (o *StartMtaOperationAccepted) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 61 | 62 | // response header Location 63 | 64 | location, err := formats.Parse("uri", response.GetHeader("Location")) 65 | if err != nil { 66 | return errors.InvalidType("Location", "header", "strfmt.URI", response.GetHeader("Location")) 67 | } 68 | o.Location = *(location.(*strfmt.URI)) 69 | 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /clients/mtaclient_v2/fakes/fake_mta_v2_client_builder.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 5 | ) 6 | 7 | type FakeMtaV2ClientBuilder struct { 8 | FakeMtaV2Client *FakeMtaV2ClientOperations 9 | } 10 | 11 | func NewFakeMtaV2ClientBuilder() *FakeMtaV2ClientBuilder { 12 | return &FakeMtaV2ClientBuilder{&FakeMtaV2ClientOperations{}} 13 | } 14 | 15 | func (fb *FakeMtaV2ClientBuilder) GetMtas(mtaID string, namespace *string, spaceGuid string, resultMta []*models.Mta, resultError error) *FakeMtaV2ClientBuilder { 16 | fb.FakeMtaV2Client.GetMtasReturns(resultMta, resultError) 17 | return fb 18 | } 19 | 20 | func (fb *FakeMtaV2ClientBuilder) GetMtasForThisSpace(mtaID string, namespace *string, resultMta []*models.Mta, resultError error) *FakeMtaV2ClientBuilder { 21 | fb.FakeMtaV2Client.GetMtasForThisSpaceReturns(resultMta, resultError) 22 | return fb 23 | } 24 | 25 | func (fb *FakeMtaV2ClientBuilder) Build() *FakeMtaV2ClientOperations { 26 | return fb.FakeMtaV2Client 27 | } 28 | -------------------------------------------------------------------------------- /clients/mtaclient_v2/mta_v2_client_operations.go: -------------------------------------------------------------------------------- 1 | package mtaclient_v2 2 | 3 | import ( 4 | models "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 5 | strfmt "github.com/go-openapi/strfmt" 6 | ) 7 | 8 | // interface for all operations provided by the v2 client 9 | type MtaV2ClientOperations interface { 10 | GetMtas(name, namespace *string, spaceGuid string) ([]*models.Mta, error) 11 | GetMtasForThisSpace(name, namespace *string) ([]*models.Mta, error) 12 | } 13 | 14 | // ResponseHeader response header 15 | type ResponseHeader struct { 16 | Location strfmt.URI 17 | } 18 | -------------------------------------------------------------------------------- /clients/mtaclient_v2/mta_v2_rest_client.go: -------------------------------------------------------------------------------- 1 | package mtaclient_v2 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 9 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient_v2/operations" 10 | "github.com/go-openapi/runtime" 11 | "github.com/go-openapi/strfmt" 12 | ) 13 | 14 | const restBaseURL string = "" 15 | 16 | type MtaV2RestClient struct { 17 | baseclient.BaseClient 18 | client *HTTPMtaV2 19 | spaceGUID string 20 | } 21 | 22 | func NewMtaClient(host string, spaceGUID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) MtaV2ClientOperations { 23 | t := baseclient.NewHTTPTransport(host, restBaseURL, rt) 24 | httpMtaV2Client := New(t, strfmt.Default) 25 | return &MtaV2RestClient{baseclient.BaseClient{TokenFactory: tokenFactory}, httpMtaV2Client, spaceGUID} 26 | } 27 | 28 | func (c MtaV2RestClient) GetMtas(name, namespace *string, spaceGuid string) ([]*models.Mta, error) { 29 | params := &operations.GetMtasV2Params{ 30 | Context: context.TODO(), 31 | Name: name, 32 | Namespace: namespace, 33 | SpaceGUID: spaceGuid, 34 | } 35 | token, err := c.TokenFactory.NewToken() 36 | if err != nil { 37 | return nil, baseclient.NewClientError(err) 38 | } 39 | resp, err := c.client.Operations.GetMtasV2(params, token) 40 | if err != nil { 41 | return nil, baseclient.NewClientError(err) 42 | } 43 | return resp.Payload, nil 44 | } 45 | 46 | func (c MtaV2RestClient) GetMtasForThisSpace(name, namespace *string) ([]*models.Mta, error) { 47 | return c.GetMtas(name, namespace, c.spaceGUID) 48 | } 49 | 50 | func executeRestOperation(tokenProvider baseclient.TokenFactory, restOperation func(token runtime.ClientAuthInfoWriter) (interface{}, error)) (interface{}, error) { 51 | token, err := tokenProvider.NewToken() 52 | if err != nil { 53 | return nil, baseclient.NewClientError(err) 54 | } 55 | return restOperation(token) 56 | } 57 | -------------------------------------------------------------------------------- /clients/mtaclient_v2/operations/get_mtas_v2_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | 14 | strfmt "github.com/go-openapi/strfmt" 15 | 16 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 17 | models "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 18 | ) 19 | 20 | // GetMtasV2Reader is a Reader for the GetMtasV2 structure. 21 | type GetMtasV2Reader struct { 22 | formats strfmt.Registry 23 | } 24 | 25 | // ReadResponse reads a server response into the received o. 26 | func (o *GetMtasV2Reader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 27 | switch response.Code() { 28 | case 200: 29 | result := NewGetMtasV2OK() 30 | if err := result.readResponse(response, consumer, o.formats); err != nil { 31 | return nil, err 32 | } 33 | return result, nil 34 | 35 | default: 36 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 37 | } 38 | } 39 | 40 | // NewGetMtasV2OK creates a GetMtasV2OK with default headers values 41 | func NewGetMtasV2OK() *GetMtasV2OK { 42 | return &GetMtasV2OK{} 43 | } 44 | 45 | /*GetMtasV2OK handles this case with default header values. 46 | 47 | OK 48 | */ 49 | type GetMtasV2OK struct { 50 | Payload []*models.Mta 51 | } 52 | 53 | func (o *GetMtasV2OK) Error() string { 54 | return fmt.Sprintf("[GET /api/v2/spaces/{spaceGuid}/mtas][%d] getMtasV2OK %+v", 200, o.Payload) 55 | } 56 | 57 | func (o *GetMtasV2OK) GetPayload() []*models.Mta { 58 | return o.Payload 59 | } 60 | 61 | func (o *GetMtasV2OK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 62 | 63 | // response payload 64 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 65 | return err 66 | } 67 | 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /clients/mtaclient_v2/operations/operations_client.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/runtime" 12 | 13 | strfmt "github.com/go-openapi/strfmt" 14 | ) 15 | 16 | // New creates a new operations API client. 17 | func New(transport runtime.ClientTransport, formats strfmt.Registry) *Client { 18 | return &Client{transport: transport, formats: formats} 19 | } 20 | 21 | /* 22 | Client for operations API 23 | */ 24 | type Client struct { 25 | transport runtime.ClientTransport 26 | formats strfmt.Registry 27 | } 28 | 29 | /* 30 | GetMtasV2 Retrieves all Multi-Target Applications in a space 31 | */ 32 | func (a *Client) GetMtasV2(params *GetMtasV2Params, authInfo runtime.ClientAuthInfoWriter) (*GetMtasV2OK, error) { 33 | // TODO: Validate the params before sending 34 | if params == nil { 35 | params = NewGetMtasV2Params() 36 | } 37 | 38 | result, err := a.transport.Submit(&runtime.ClientOperation{ 39 | ID: "getMtasV2", 40 | Method: "GET", 41 | PathPattern: "/api/v2/spaces/{spaceGuid}/mtas", 42 | ProducesMediaTypes: []string{"application/json", "application/json;charset=UTF-8"}, 43 | ConsumesMediaTypes: []string{""}, 44 | Schemes: []string{"https"}, 45 | Params: params, 46 | Reader: &GetMtasV2Reader{formats: a.formats}, 47 | AuthInfo: authInfo, 48 | Context: params.Context, 49 | Client: params.HTTPClient, 50 | }) 51 | if err != nil { 52 | return nil, err 53 | } 54 | success, ok := result.(*GetMtasV2OK) 55 | if ok { 56 | return success, nil 57 | } 58 | // unexpected success response 59 | // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue 60 | msg := fmt.Sprintf("unexpected success response for getMtasV2: API contract not enforced by server. Client expected to get an error, but got: %T", result) 61 | panic(msg) 62 | } 63 | 64 | // SetTransport changes the transport on the client 65 | func (a *Client) SetTransport(transport runtime.ClientTransport) { 66 | a.transport = transport 67 | } 68 | -------------------------------------------------------------------------------- /clients/mtaclient_v2/retryable_mta_v2_rest_client.go: -------------------------------------------------------------------------------- 1 | package mtaclient_v2 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 9 | ) 10 | 11 | type RetryableMtaRestClient struct { 12 | mtaClient MtaV2ClientOperations 13 | MaxRetriesCount int 14 | RetryInterval time.Duration 15 | } 16 | 17 | func NewRetryableMtaRestClient(host string, spaceGUID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) RetryableMtaRestClient { 18 | mtaClient := NewMtaClient(host, spaceGUID, rt, tokenFactory) 19 | return RetryableMtaRestClient{mtaClient: mtaClient, MaxRetriesCount: 3, RetryInterval: time.Second * 3} 20 | } 21 | 22 | func (c RetryableMtaRestClient) GetMtas(name, namespace *string, spaceGuid string) ([]*models.Mta, error) { 23 | getMtasCb := func() (interface{}, error) { 24 | return c.mtaClient.GetMtas(name, namespace, spaceGuid) 25 | } 26 | resp, err := baseclient.CallWithRetry(getMtasCb, c.MaxRetriesCount, c.RetryInterval) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return resp.([]*models.Mta), nil 31 | } 32 | 33 | func (c RetryableMtaRestClient) GetMtasForThisSpace(name, namespace *string) ([]*models.Mta, error) { 34 | getMtasCb := func() (interface{}, error) { 35 | return c.mtaClient.GetMtasForThisSpace(name, namespace) 36 | } 37 | resp, err := baseclient.CallWithRetry(getMtasCb, c.MaxRetriesCount, c.RetryInterval) 38 | if err != nil { 39 | return nil, err 40 | } 41 | return resp.([]*models.Mta), nil 42 | } 43 | -------------------------------------------------------------------------------- /clients/restclient/fakes/fake_rest_client_builder.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 5 | ) 6 | 7 | type mtaResult struct { 8 | *models.Mta 9 | error 10 | } 11 | 12 | // FakeRestClientBuilder is a builder of FakeRestClientOperations instances 13 | type FakeRestClientBuilder struct { 14 | fakeRestClient FakeRestClientOperations 15 | mtaResults map[string]mtaResult 16 | } 17 | 18 | // NewFakeRestClientBuilder creates a new builder 19 | func NewFakeRestClientBuilder() *FakeRestClientBuilder { 20 | return &FakeRestClientBuilder{} 21 | } 22 | 23 | // Build builds a FakeRestClientOperations instance 24 | func (b *FakeRestClientBuilder) Build() *FakeRestClientOperations { 25 | return &b.fakeRestClient 26 | } 27 | -------------------------------------------------------------------------------- /clients/restclient/fakes/fake_rest_client_operations.go: -------------------------------------------------------------------------------- 1 | // This file was generated by counterfeiter 2 | package fakes 3 | 4 | import ( 5 | "sync" 6 | 7 | restclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/restclient" 8 | ) 9 | 10 | type FakeRestClientOperations struct { 11 | PurgeConfigurationStub func(org, space string) error 12 | purgeConfigurationMutex sync.RWMutex 13 | purgeConfigurationArgsForCall []struct { 14 | org string 15 | space string 16 | } 17 | purgeConfigurationReturns struct { 18 | result1 error 19 | } 20 | } 21 | 22 | func (fake *FakeRestClientOperations) PurgeConfiguration(org string, space string) error { 23 | fake.purgeConfigurationMutex.Lock() 24 | fake.purgeConfigurationArgsForCall = append(fake.purgeConfigurationArgsForCall, struct { 25 | org string 26 | space string 27 | }{org, space}) 28 | fake.purgeConfigurationMutex.Unlock() 29 | if fake.PurgeConfigurationStub != nil { 30 | return fake.PurgeConfigurationStub(org, space) 31 | } else { 32 | return fake.purgeConfigurationReturns.result1 33 | } 34 | } 35 | func (fake *FakeRestClientOperations) PurgeConfigurationCallCount() int { 36 | fake.purgeConfigurationMutex.RLock() 37 | defer fake.purgeConfigurationMutex.RUnlock() 38 | return len(fake.purgeConfigurationArgsForCall) 39 | } 40 | 41 | func (fake *FakeRestClientOperations) PurgeConfigurationArgsForCall(i int) (string, string) { 42 | fake.purgeConfigurationMutex.RLock() 43 | defer fake.purgeConfigurationMutex.RUnlock() 44 | return fake.purgeConfigurationArgsForCall[i].org, fake.purgeConfigurationArgsForCall[i].space 45 | } 46 | 47 | func (fake *FakeRestClientOperations) PurgeConfigurationReturns(result1 error) { 48 | fake.PurgeConfigurationStub = nil 49 | fake.purgeConfigurationReturns = struct { 50 | result1 error 51 | }{result1} 52 | } 53 | 54 | var _ restclient.RestClientOperations = new(FakeRestClientOperations) 55 | -------------------------------------------------------------------------------- /clients/restclient/operations/get_csrf_token_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/runtime" 12 | 13 | strfmt "github.com/go-openapi/strfmt" 14 | 15 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 16 | ) 17 | 18 | // GetCsrfTokenReader is a Reader for the GetCsrfToken structure. 19 | type GetCsrfTokenReader struct { 20 | formats strfmt.Registry 21 | } 22 | 23 | // ReadResponse reads a server response into the received o. 24 | func (o *GetCsrfTokenReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 25 | switch response.Code() { 26 | 27 | case 204: 28 | result := NewGetCsrfTokenNoContent() 29 | if err := result.readResponse(response, consumer, o.formats); err != nil { 30 | return nil, err 31 | } 32 | return result, nil 33 | 34 | default: 35 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 36 | } 37 | } 38 | 39 | // NewGetCsrfTokenNoContent creates a GetCsrfTokenNoContent with default headers values 40 | func NewGetCsrfTokenNoContent() *GetCsrfTokenNoContent { 41 | return &GetCsrfTokenNoContent{} 42 | } 43 | 44 | /*GetCsrfTokenNoContent handles this case with default header values. 45 | 46 | No Content 47 | */ 48 | type GetCsrfTokenNoContent struct { 49 | } 50 | 51 | func (o *GetCsrfTokenNoContent) Error() string { 52 | return fmt.Sprintf("[GET /csrf-token][%d] getCsrfTokenNoContent ", 204) 53 | } 54 | 55 | func (o *GetCsrfTokenNoContent) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 56 | 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /clients/restclient/operations/operations_client.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "github.com/go-openapi/runtime" 10 | 11 | strfmt "github.com/go-openapi/strfmt" 12 | ) 13 | 14 | // New creates a new operations API client. 15 | func New(transport runtime.ClientTransport, formats strfmt.Registry) *Client { 16 | return &Client{transport: transport, formats: formats} 17 | } 18 | 19 | /* 20 | Client for operations API 21 | */ 22 | type Client struct { 23 | transport runtime.ClientTransport 24 | formats strfmt.Registry 25 | } 26 | 27 | /* 28 | PurgeConfiguration purge configuration API 29 | */ 30 | func (a *Client) PurgeConfiguration(params *PurgeConfigurationParams, authInfo runtime.ClientAuthInfoWriter) (*PurgeConfigurationNoContent, error) { 31 | // TODO: Validate the params before sending 32 | if params == nil { 33 | params = NewPurgeConfigurationParams() 34 | } 35 | 36 | result, err := a.transport.Submit(&runtime.ClientOperation{ 37 | ID: "PurgeConfiguration", 38 | Method: "POST", 39 | PathPattern: "/configuration-entries/purge", 40 | ProducesMediaTypes: []string{"application/xml"}, 41 | ConsumesMediaTypes: []string{"application/xml"}, 42 | Schemes: []string{"https"}, 43 | Params: params, 44 | Reader: &PurgeConfigurationReader{formats: a.formats}, 45 | AuthInfo: authInfo, 46 | Context: params.Context, 47 | Client: params.HTTPClient, 48 | }) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return result.(*PurgeConfigurationNoContent), nil 53 | 54 | } 55 | 56 | // SetTransport changes the transport on the client 57 | func (a *Client) SetTransport(transport runtime.ClientTransport) { 58 | a.transport = transport 59 | } 60 | 61 | /* 62 | GetCsrfToken Retrieves a csrf-token header 63 | 64 | */ 65 | func (a *Client) GetCsrfToken(params *GetCsrfTokenParams, authInfo runtime.ClientAuthInfoWriter) (*GetCsrfTokenNoContent, error) { 66 | // TODO: Validate the params before sending 67 | if params == nil { 68 | params = NewGetCsrfTokenParams() 69 | } 70 | 71 | result, err := a.transport.Submit(&runtime.ClientOperation{ 72 | ID: "getCsrfToken", 73 | Method: "GET", 74 | PathPattern: "/csrf-token", 75 | ProducesMediaTypes: []string{"application/json"}, 76 | ConsumesMediaTypes: []string{"application/json"}, 77 | Schemes: []string{"https"}, 78 | Params: params, 79 | Reader: &GetCsrfTokenReader{formats: a.formats}, 80 | AuthInfo: authInfo, 81 | Context: params.Context, 82 | Client: params.HTTPClient, 83 | }) 84 | if err != nil { 85 | return nil, err 86 | } 87 | return result.(*GetCsrfTokenNoContent), nil 88 | 89 | } 90 | -------------------------------------------------------------------------------- /clients/restclient/operations/purge_configuration_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package operations 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/runtime" 12 | 13 | strfmt "github.com/go-openapi/strfmt" 14 | 15 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 16 | ) 17 | 18 | // PurgeConfigurationReader is a Reader for the PurgeConfiguration structure. 19 | type PurgeConfigurationReader struct { 20 | formats strfmt.Registry 21 | } 22 | 23 | // ReadResponse reads a server response into the received o. 24 | func (o *PurgeConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 25 | switch response.Code() { 26 | 27 | case 204: 28 | result := NewPurgeConfigurationNoContent() 29 | if err := result.readResponse(response, consumer, o.formats); err != nil { 30 | return nil, err 31 | } 32 | return result, nil 33 | 34 | default: 35 | return nil, baseclient.BuildErrorResponse(response, consumer, o.formats) 36 | } 37 | } 38 | 39 | // NewPurgeConfigurationNoContent creates a PurgeConfigurationNoContent with default headers values 40 | func NewPurgeConfigurationNoContent() *PurgeConfigurationNoContent { 41 | return &PurgeConfigurationNoContent{} 42 | } 43 | 44 | /*PurgeConfigurationNoContent handles this case with default header values. 45 | 46 | No Content 47 | */ 48 | type PurgeConfigurationNoContent struct { 49 | } 50 | 51 | func (o *PurgeConfigurationNoContent) Error() string { 52 | return fmt.Sprintf("[POST /configuration-entries/purge][%d] purgeConfigurationNoContent ", 204) 53 | } 54 | 55 | func (o *PurgeConfigurationNoContent) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 56 | 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /clients/restclient/rest_client.go: -------------------------------------------------------------------------------- 1 | package restclient 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/go-openapi/runtime" 8 | "github.com/go-openapi/strfmt" 9 | 10 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 11 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/restclient/operations" 12 | ) 13 | 14 | const restBaseURL string = "rest/" 15 | const csrfRestBaseURL string = "api/v1/" 16 | 17 | // RestClient represents a client for the MTA deployer REST protocol 18 | type RestClient struct { 19 | baseclient.BaseClient 20 | Client *Rest 21 | } 22 | 23 | // NewRestClient creates a new Rest client 24 | func NewRestClient(host string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) RestClientOperations { 25 | t := baseclient.NewHTTPTransport(host, restBaseURL, rt) 26 | client := New(t, strfmt.Default) 27 | return RestClient{baseclient.BaseClient{tokenFactory}, client} 28 | } 29 | 30 | func (c RestClient) PurgeConfiguration(org, space string) error { 31 | params := &operations.PurgeConfigurationParams{ 32 | Org: org, 33 | Space: space, 34 | Context: context.TODO(), 35 | } 36 | _, err := executeRestOperation(c.TokenFactory, func(token runtime.ClientAuthInfoWriter) (interface{}, error) { 37 | return c.Client.Operations.PurgeConfiguration(params, token) 38 | }) 39 | if err != nil { 40 | return baseclient.NewClientError(err) 41 | } 42 | return nil 43 | } 44 | 45 | func executeRestOperation(tokenProvider baseclient.TokenFactory, restOperation func(token runtime.ClientAuthInfoWriter) (interface{}, error)) (interface{}, error) { 46 | token, err := tokenProvider.NewToken() 47 | if err != nil { 48 | return nil, baseclient.NewClientError(err) 49 | } 50 | return restOperation(token) 51 | } 52 | -------------------------------------------------------------------------------- /clients/restclient/rest_client_operations.go: -------------------------------------------------------------------------------- 1 | package restclient 2 | 3 | // RestClientOperations is an interface having all RestClient operations 4 | type RestClientOperations interface { 5 | PurgeConfiguration(org, space string) error 6 | } 7 | -------------------------------------------------------------------------------- /clients/restclient/rest_client_test.go: -------------------------------------------------------------------------------- 1 | package restclient_test 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/restclient" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/testutil" 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | "net/http" 9 | ) 10 | 11 | var _ = Describe("RestClient", func() { 12 | 13 | Describe("PurgeConfiguration", func() { 14 | Context("when the backend returns not 204 No Content", func() { 15 | It("should return an error", func() { 16 | client := newRestClient(http.StatusInternalServerError) 17 | err := client.PurgeConfiguration("org", "space") 18 | Ω(err).Should(HaveOccurred()) 19 | }) 20 | }) 21 | 22 | Context("when the backend returns 204 No Content", func() { 23 | It("should not return an error", func() { 24 | client := newRestClient(http.StatusNoContent) 25 | err := client.PurgeConfiguration("org", "space") 26 | Ω(err).ShouldNot(HaveOccurred()) 27 | }) 28 | }) 29 | }) 30 | }) 31 | 32 | func newRestClient(statusCode int) restclient.RestClientOperations { 33 | tokenFactory := testutil.NewCustomTokenFactory("test-token") 34 | roundTripper := testutil.NewCustomTransport(statusCode) 35 | return restclient.NewRestClient("http://localhost:1000", roundTripper, tokenFactory) 36 | } 37 | -------------------------------------------------------------------------------- /clients/restclient/restclient_suite_test.go: -------------------------------------------------------------------------------- 1 | package restclient_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestRestclient(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Restclient Suite") 13 | } 14 | -------------------------------------------------------------------------------- /clients/restclient/retryable_rest_client.go: -------------------------------------------------------------------------------- 1 | package restclient 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | 7 | baseclient "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 8 | ) 9 | 10 | // RetryableRestClient represents retryable REST client for the MTA deployer REST protocol 11 | type RetryableRestClient struct { 12 | RestClient RestClientOperations 13 | MaxRetriesCount int 14 | RetryInterval time.Duration 15 | } 16 | 17 | // NewRetryableRestClient creates a new retryable REST client 18 | func NewRetryableRestClient(host string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) RestClientOperations { 19 | restClient := NewRestClient(host, rt, tokenFactory) 20 | return RetryableRestClient{restClient, 3, time.Second * 3} 21 | } 22 | 23 | // PurgeConfiguration purges a configuration 24 | func (c RetryableRestClient) PurgeConfiguration(org, space string) error { 25 | purgeConfigurationCb := func() (interface{}, error) { 26 | return nil, c.RestClient.PurgeConfiguration(org, space) 27 | } 28 | _, err := baseclient.CallWithRetry(purgeConfigurationCb, c.MaxRetriesCount, c.RetryInterval) 29 | return err 30 | } 31 | -------------------------------------------------------------------------------- /clients/swagger/rest.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | version: 1.2.1 4 | title: MTA Deployer REST Protocol 5 | host: example.com 6 | basePath: /rest/ 7 | securityDefinitions: 8 | basic: 9 | type: basic 10 | oauth2: 11 | type: oauth2 12 | tokenUrl: https://uaa.bosh-lite.com/oauth/token 13 | flow: password 14 | scopes: {} 15 | security: 16 | - oauth2: [] 17 | schemes: 18 | - https 19 | consumes: 20 | - application/xml 21 | produces: 22 | - application/xml 23 | paths: 24 | /configuration-entries/purge: 25 | post: 26 | operationId: PurgeConfiguration 27 | responses: 28 | 204: 29 | description: No Content 30 | parameters: 31 | - $ref: "#/parameters/org" 32 | - $ref: "#/parameters/space" 33 | parameters: 34 | org: 35 | name: org 36 | in: query 37 | required: true 38 | type: string 39 | space: 40 | name: space 41 | in: query 42 | required: true 43 | type: string 44 | -------------------------------------------------------------------------------- /commands/command.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "code.cloudfoundry.org/cli/plugin" 5 | "flag" 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 7 | ) 8 | 9 | // Command is an interface that should be implemented by all commands 10 | type Command interface { 11 | GetPluginCommand() plugin.Command 12 | Initialize(name string, cliConnection plugin.CliConnection) 13 | Execute(args []string) ExecutionStatus 14 | 15 | executeInternal(positionalArgs []string, dsUrl string, flags *flag.FlagSet, cfTarget util.CloudFoundryTarget) ExecutionStatus 16 | defineCommandOptions(flags *flag.FlagSet) 17 | } 18 | -------------------------------------------------------------------------------- /commands/commands_suite_test.go: -------------------------------------------------------------------------------- 1 | package commands_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestCommands(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Commands Suite") 13 | } 14 | -------------------------------------------------------------------------------- /commands/default_token_factory.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | "time" 8 | 9 | "code.cloudfoundry.org/cli/plugin" 10 | "github.com/go-openapi/runtime" 11 | "github.com/go-openapi/runtime/client" 12 | "github.com/golang-jwt/jwt/v5" 13 | ) 14 | 15 | // DefaultTokenFactory factory for retrieving tokens 16 | type DefaultTokenFactory struct { 17 | cliConnection plugin.CliConnection 18 | cachedToken string 19 | cachedTokenTime int64 20 | } 21 | 22 | // NewDefaultTokenFactory creates default token factory 23 | func NewDefaultTokenFactory(cliConnection plugin.CliConnection) *DefaultTokenFactory { 24 | return &DefaultTokenFactory{ 25 | cliConnection: cliConnection, 26 | } 27 | } 28 | 29 | // NewToken retrives outh token 30 | func (t *DefaultTokenFactory) NewToken() (runtime.ClientAuthInfoWriter, error) { 31 | rawToken, err := t.NewRawToken() 32 | return client.BearerToken(rawToken), err 33 | } 34 | 35 | func (t *DefaultTokenFactory) NewRawToken() (string, error) { 36 | var expirationTime int64 37 | if t.cachedToken != "" { 38 | var err error 39 | expirationTime, err = getTokenExpirationTime(t.cachedToken) 40 | if err != nil { 41 | return "", err 42 | } 43 | } 44 | currentTimeInSeconds := time.Now().Unix() 45 | expirationTime = (expirationTime - currentTimeInSeconds) / 2 46 | if currentTimeInSeconds-t.cachedTokenTime >= expirationTime { 47 | tokenString, err := t.cliConnection.AccessToken() 48 | if err != nil { 49 | return "", fmt.Errorf("Could not get access token: %s", err) 50 | } 51 | t.cachedTokenTime = currentTimeInSeconds 52 | t.cachedToken = getTokenValue(tokenString) 53 | } 54 | return t.cachedToken, nil 55 | } 56 | 57 | func getTokenExpirationTime(tokenString string) (int64, error) { 58 | // Parse jwt token string 59 | parser := jwt.NewParser(jwt.WithoutClaimsValidation()) 60 | token, err := parser.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { 61 | return token, nil 62 | }) 63 | 64 | if err != nil && !strings.Contains(err.Error(), "key is of invalid type") { 65 | return 0, err 66 | } 67 | 68 | // Try to get token expiration time 69 | claims, ok := token.Claims.(jwt.MapClaims) 70 | if !ok { 71 | return 0, errors.New("Could not read token claims") 72 | } 73 | if value, ok := claims["exp"]; ok { 74 | return int64(value.(float64)), nil 75 | } 76 | return 0, errors.New("Could not get token exipiration time") 77 | } 78 | -------------------------------------------------------------------------------- /commands/deployment_strategy.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "flag" 5 | "strconv" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 8 | ) 9 | 10 | type DeploymentStrategy interface { 11 | CreateProcessBuilder() *util.ProcessBuilder 12 | } 13 | 14 | type DeployCommandDeploymentStrategy struct{} 15 | 16 | func (d *DeployCommandDeploymentStrategy) CreateProcessBuilder() *util.ProcessBuilder { 17 | processBuilder := util.NewProcessBuilder() 18 | processBuilder.ProcessType((deployCommandProcessTypeProvider{}).GetProcessType()) 19 | return processBuilder 20 | } 21 | 22 | type BlueGreenDeployCommandDeploymentStrategy struct { 23 | noConfirm bool 24 | skipIdleStart bool 25 | incrementalDeploy bool 26 | shouldBackupPreviousVersion bool 27 | } 28 | 29 | func (b *BlueGreenDeployCommandDeploymentStrategy) CreateProcessBuilder() *util.ProcessBuilder { 30 | processBuilder := util.NewProcessBuilder() 31 | processBuilder.ProcessType((blueGreenDeployCommandProcessTypeProvider{}).GetProcessType()) 32 | processBuilder.Parameter("noConfirm", strconv.FormatBool(b.noConfirm)) 33 | processBuilder.Parameter("skipIdleStart", strconv.FormatBool(b.skipIdleStart)) 34 | processBuilder.Parameter("keepOriginalAppNamesAfterDeploy", strconv.FormatBool(true)) 35 | processBuilder.Parameter("shouldApplyIncrementalInstancesUpdate", strconv.FormatBool(b.incrementalDeploy)) 36 | processBuilder.Parameter("shouldBackupPreviousVersion", strconv.FormatBool(b.shouldBackupPreviousVersion)) 37 | return processBuilder 38 | } 39 | 40 | func NewDeploymentStrategy(flags *flag.FlagSet, typeProvider ProcessTypeProvider) DeploymentStrategy { 41 | if typeProvider.GetProcessType() == (blueGreenDeployCommandProcessTypeProvider{}).GetProcessType() { 42 | return &BlueGreenDeployCommandDeploymentStrategy{GetBoolOpt(noConfirmOpt, flags), GetBoolOpt(skipIdleStart, flags), isIncrementalBlueGreen(flags), GetBoolOpt(shouldBackupPreviousVersionOpt, flags)} 43 | } 44 | strategy := GetStringOpt(strategyOpt, flags) 45 | if strategy == "default" { 46 | return &DeployCommandDeploymentStrategy{} 47 | } 48 | if GetBoolOpt(skipIdleStart, flags) { 49 | return &BlueGreenDeployCommandDeploymentStrategy{true, true, isIncrementalBlueGreen(flags), GetBoolOpt(shouldBackupPreviousVersionOpt, flags)} 50 | } 51 | return &BlueGreenDeployCommandDeploymentStrategy{GetBoolOpt(skipTestingPhase, flags), false, isIncrementalBlueGreen(flags), GetBoolOpt(shouldBackupPreviousVersionOpt, flags)} 52 | } 53 | 54 | func isIncrementalBlueGreen(flags *flag.FlagSet) bool { 55 | strategy := GetStringOpt(strategyOpt, flags) 56 | return strategy == "incremental-blue-green" 57 | } 58 | 59 | func AvailableStrategies() []string { 60 | return []string{"blue-green", "incremental-blue-green", "default"} 61 | } 62 | -------------------------------------------------------------------------------- /commands/execution_status.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | type ExecutionStatus int 4 | 5 | const ( 6 | Success ExecutionStatus = 0 7 | Failure ExecutionStatus = 1 8 | ) 9 | 10 | func (status ExecutionStatus) ToInt() int { 11 | return int(status) 12 | } 13 | -------------------------------------------------------------------------------- /commands/fakes/fake_process_type_provider.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | type FakeDeployCommandProcessTypeProvider struct {} 4 | 5 | func (FakeDeployCommandProcessTypeProvider) GetProcessType() string { 6 | return "DEPLOY" 7 | } 8 | 9 | type FakeBlueGreenCommandProcessTypeProvider struct {} 10 | 11 | func (FakeBlueGreenCommandProcessTypeProvider) GetProcessType() string { 12 | return "BLUE_GREEN_DEPLOY" 13 | } 14 | -------------------------------------------------------------------------------- /commands/monitor_action.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "code.cloudfoundry.org/cli/cf/terminal" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient" 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 7 | ) 8 | 9 | // MonitorAction monitors process execution 10 | type MonitorAction struct { 11 | commandName string 12 | monitoringRetries uint 13 | } 14 | 15 | // Execute executes monitor action on process with the specified id 16 | func (a *MonitorAction) Execute(operationID string, mtaClient mtaclient.MtaClientOperations) ExecutionStatus { 17 | operation, err := getMonitoringOperation(operationID, mtaClient) 18 | if err != nil { 19 | ui.Failed("Could not monitor operation %s: %s", terminal.EntityNameColor(operationID), err) 20 | return Failure 21 | } 22 | 23 | return NewExecutionMonitor(a.commandName, operationID, "messages", a.monitoringRetries, operation.Messages, mtaClient).Monitor() 24 | } 25 | -------------------------------------------------------------------------------- /commands/mtas_command.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "code.cloudfoundry.org/cli/cf/terminal" 5 | "code.cloudfoundry.org/cli/plugin" 6 | "flag" 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 9 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 10 | ) 11 | 12 | // MtasCommand is a command for listing all deployed MTAs 13 | type MtasCommand struct { 14 | *BaseCommand 15 | } 16 | 17 | func NewMtasCommand() *MtasCommand { 18 | baseCmd := &BaseCommand{flagsParser: NewDefaultCommandFlagsParser(nil), flagsValidator: NewDefaultCommandFlagsValidator(nil)} 19 | mtasCmd := &MtasCommand{baseCmd} 20 | baseCmd.Command = mtasCmd 21 | return mtasCmd 22 | } 23 | 24 | // GetPluginCommand returns the plugin command details 25 | func (c *MtasCommand) GetPluginCommand() plugin.Command { 26 | return plugin.Command{ 27 | Name: "mtas", 28 | HelpText: "List all multi-target apps", 29 | UsageDetails: plugin.Usage{ 30 | Usage: "cf mtas [-u URL]", 31 | Options: map[string]string{ 32 | deployServiceURLOpt: "Deploy service URL, by default 'deploy-service.'", 33 | }, 34 | }, 35 | } 36 | } 37 | 38 | func (c *MtasCommand) defineCommandOptions(flags *flag.FlagSet) { 39 | //no additional options to define 40 | } 41 | 42 | func (c *MtasCommand) executeInternal(positionalArgs []string, dsHost string, flags *flag.FlagSet, cfTarget util.CloudFoundryTarget) ExecutionStatus { 43 | // Print initial message 44 | ui.Say("Getting multi-target apps in org %s / space %s as %s...", 45 | terminal.EntityNameColor(cfTarget.Org.Name), terminal.EntityNameColor(cfTarget.Space.Name), 46 | terminal.EntityNameColor(cfTarget.Username)) 47 | 48 | // Create new REST client 49 | mtaV2Client := c.NewMtaV2Client(dsHost, cfTarget) 50 | 51 | // Get all deployed components 52 | mtas, err := mtaV2Client.GetMtasForThisSpace(nil, nil) 53 | if err != nil { 54 | ui.Failed("Could not get deployed components: %s", baseclient.NewClientError(err)) 55 | return Failure 56 | } 57 | ui.Ok() 58 | 59 | // Print all deployed MTAs 60 | if len(mtas) > 0 { 61 | table := ui.Table([]string{"mta id", "version", "namespace"}) 62 | for _, mta := range mtas { 63 | table.Add(mta.Metadata.ID, util.GetMtaVersionAsString(mta), mta.Metadata.Namespace) 64 | } 65 | table.Print() 66 | } else { 67 | ui.Say("No multi-target apps found") 68 | } 69 | return Success 70 | } 71 | -------------------------------------------------------------------------------- /commands/process_type_provider.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | type ProcessTypeProvider interface { 4 | GetProcessType() string 5 | } 6 | -------------------------------------------------------------------------------- /commands/purge_config_command.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "code.cloudfoundry.org/cli/cf/terminal" 5 | "code.cloudfoundry.org/cli/plugin" 6 | "flag" 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 9 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 10 | ) 11 | 12 | type PurgeConfigCommand struct { 13 | *BaseCommand 14 | } 15 | 16 | func NewPurgeConfigCommand() *PurgeConfigCommand { 17 | baseCmd := &BaseCommand{flagsParser: NewDefaultCommandFlagsParser(nil), flagsValidator: NewDefaultCommandFlagsValidator(nil)} 18 | purgeConfigCmd := &PurgeConfigCommand{baseCmd} 19 | baseCmd.Command = purgeConfigCmd 20 | return purgeConfigCmd 21 | } 22 | 23 | func (c *PurgeConfigCommand) GetPluginCommand() plugin.Command { 24 | return plugin.Command{ 25 | Name: "purge-mta-config", 26 | HelpText: "Purge no longer valid configuration entries", 27 | UsageDetails: plugin.Usage{ 28 | Usage: "cf purge-mta-config [-u URL]", 29 | Options: map[string]string{ 30 | deployServiceURLOpt: "Deploy service URL, by default 'deploy-service.'", 31 | }, 32 | }, 33 | } 34 | } 35 | 36 | func (c *PurgeConfigCommand) defineCommandOptions(flags *flag.FlagSet) { 37 | //no additional options to define 38 | } 39 | 40 | func (c *PurgeConfigCommand) executeInternal(positionalArgs []string, dsHost string, flags *flag.FlagSet, cfTarget util.CloudFoundryTarget) ExecutionStatus { 41 | ui.Say("Purging configuration entries in org %s / space %s as %s", 42 | terminal.EntityNameColor(cfTarget.Org.Name), terminal.EntityNameColor(cfTarget.Space.Name), 43 | terminal.EntityNameColor(cfTarget.Username)) 44 | 45 | rc := c.NewRestClient(dsHost) 46 | // TODO: ensure session 47 | 48 | if err := rc.PurgeConfiguration(cfTarget.Org.Name, cfTarget.Space.Name); err != nil { 49 | ui.Failed("Could not purge configuration: %v\n", baseclient.NewClientError(err)) 50 | return Failure 51 | } 52 | ui.Ok() 53 | return Success 54 | } 55 | -------------------------------------------------------------------------------- /commands/purge_config_command_test.go: -------------------------------------------------------------------------------- 1 | package commands_test 2 | 3 | import ( 4 | plugin_fakes "code.cloudfoundry.org/cli/plugin/pluginfakes" 5 | cli_fakes "github.com/cloudfoundry-incubator/multiapps-cli-plugin/cli/fakes" 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/commands" 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/testutil" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 9 | util_fakes "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util/fakes" 10 | . "github.com/onsi/ginkgo" 11 | . "github.com/onsi/gomega" 12 | ) 13 | 14 | var _ = Describe("PurgeConfigCommand", func() { 15 | 16 | Describe("Execute", func() { 17 | const ( 18 | org = "test-org" 19 | space = "test-space" 20 | user = "test-user" 21 | ) 22 | 23 | var name string 24 | var cliConnection *plugin_fakes.FakeCliConnection 25 | var clientFactory *commands.TestClientFactory 26 | var command *commands.PurgeConfigCommand 27 | var testTokenFactory *commands.TestTokenFactory 28 | 29 | var oc testutil.OutputCapturer 30 | var ex testutil.Expector 31 | 32 | BeforeEach(func() { 33 | ui.DisableTerminalOutput(true) 34 | name = "purge-mta-config" 35 | cliConnection = cli_fakes.NewFakeCliConnectionBuilder(). 36 | CurrentOrg("test-org-guid", org, nil). 37 | CurrentSpace("test-space-guid", space, nil). 38 | Username(user, nil). 39 | AccessToken("bearer test-token", nil).Build() 40 | 41 | testTokenFactory = commands.NewTestTokenFactory(cliConnection) 42 | clientFactory = commands.NewTestClientFactory(nil, nil, nil) 43 | deployServiceURLCalculator := util_fakes.NewDeployServiceURLFakeCalculator("deploy-service.test.ondemand.com") 44 | 45 | command = commands.NewPurgeConfigCommand() 46 | command.InitializeAll(name, cliConnection, testutil.NewCustomTransport(200), clientFactory, testTokenFactory, deployServiceURLCalculator) 47 | 48 | oc = testutil.NewUIOutputCapturer() 49 | ex = testutil.NewUIExpector() 50 | }) 51 | 52 | Context("with an unknown flag", func() { 53 | It("should print incorrect usage, call cf help, and exit with a non-zero status", func() { 54 | output, status := oc.CaptureOutputAndStatus(func() int { 55 | return command.Execute([]string{"-a"}).ToInt() 56 | }) 57 | ex.ExpectFailure(status, output, "Incorrect usage. Unknown or wrong flag") 58 | Expect(cliConnection.CliCommandArgsForCall(0)).To(Equal([]string{"help", name})) 59 | }) 60 | }) 61 | 62 | Context("with wrong arguments", func() { 63 | It("should print incorrect usage, call cf help, and exit with a non-zero status", func() { 64 | output, status := oc.CaptureOutputAndStatus(func() int { 65 | return command.Execute([]string{"x", "y", "z"}).ToInt() 66 | }) 67 | ex.ExpectFailure(status, output, "Incorrect usage. Wrong arguments") 68 | Expect(cliConnection.CliCommandArgsForCall(0)).To(Equal([]string{"help", name})) 69 | }) 70 | }) 71 | 72 | }) 73 | }) 74 | -------------------------------------------------------------------------------- /commands/retrier/retry_util.go: -------------------------------------------------------------------------------- 1 | package retrier 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/log" 7 | ) 8 | 9 | func Execute[T any](attempts int, callback func() (T, error), shouldRetry func(result T, err error) bool) (T, error) { 10 | for i := 0; i < attempts; i++ { 11 | result, err := callback() 12 | if shouldRetry(result, err) { 13 | logError[T](result, err) 14 | time.Sleep(3 * time.Second) 15 | continue 16 | } 17 | return result, err 18 | } 19 | return callback() 20 | } 21 | 22 | func logError[T any](result T, err error) { 23 | if err != nil { 24 | log.Tracef("retrying an operation that failed with: %v", err) 25 | } 26 | log.Tracef("result of the callback %v", result) 27 | } 28 | -------------------------------------------------------------------------------- /commands/test_client_factory.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/mtaclient_v2" 9 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/restclient" 10 | ) 11 | 12 | type TestClientFactory struct { 13 | RestClient restclient.RestClientOperations 14 | MtaClient mtaclient.MtaClientOperations 15 | MtaV2Client mtaclient_v2.MtaV2ClientOperations 16 | } 17 | 18 | func NewTestClientFactory(mtaClient mtaclient.MtaClientOperations, 19 | mtaV2client mtaclient_v2.MtaV2ClientOperations, 20 | restClient restclient.RestClientOperations) *TestClientFactory { 21 | return &TestClientFactory{ 22 | RestClient: restClient, 23 | MtaClient: mtaClient, 24 | MtaV2Client: mtaV2client, 25 | } 26 | } 27 | 28 | func (f *TestClientFactory) NewMtaClient(host, spaceID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) mtaclient.MtaClientOperations { 29 | return f.MtaClient 30 | } 31 | 32 | func (f *TestClientFactory) NewRestClient(host string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) restclient.RestClientOperations { 33 | return f.RestClient 34 | } 35 | 36 | func (f *TestClientFactory) NewMtaV2Client(host, spaceGUID string, rt http.RoundTripper, tokenFactory baseclient.TokenFactory) mtaclient_v2.MtaV2ClientOperations { 37 | return f.MtaV2Client 38 | } 39 | -------------------------------------------------------------------------------- /commands/test_token_factory.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | import ( 4 | fakes "code.cloudfoundry.org/cli/plugin/pluginfakes" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/testutil" 6 | "github.com/go-openapi/runtime" 7 | ) 8 | 9 | type TestTokenFactory struct { 10 | FakeCliConnection *fakes.FakeCliConnection 11 | } 12 | 13 | func NewTestTokenFactory(fakeCliConnection *fakes.FakeCliConnection) *TestTokenFactory { 14 | return &TestTokenFactory{ 15 | FakeCliConnection: fakeCliConnection, 16 | } 17 | } 18 | 19 | func (f *TestTokenFactory) NewToken() (runtime.ClientAuthInfoWriter, error) { 20 | tokenString, _ := f.NewRawToken() 21 | return testutil.NewCustomBearerToken(tokenString), nil 22 | } 23 | 24 | func (f *TestTokenFactory) NewRawToken() (string, error) { 25 | return f.FakeCliConnection.AccessToken() 26 | } 27 | -------------------------------------------------------------------------------- /commands/upload_from_url_status.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | type UploadFromUrlStatus struct { 4 | FileId string 5 | MtaId string 6 | ClientActions []string 7 | ExecutionStatus ExecutionStatus 8 | } 9 | -------------------------------------------------------------------------------- /configuration/configuration.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | "fmt" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/configuration/properties" 6 | "os" 7 | ) 8 | 9 | const unknownError = "An unknown error occurred during the parsing of the environment variable \"%s\". Please report this! Value type: %T" 10 | 11 | type Snapshot struct { 12 | backendURL properties.ConfigurableProperty 13 | uploadChunkSizeInMB properties.ConfigurableProperty 14 | uploadChunksSequentially properties.ConfigurableProperty 15 | disableProgressBar properties.ConfigurableProperty 16 | } 17 | 18 | func NewSnapshot() Snapshot { 19 | return Snapshot{ 20 | backendURL: properties.BackendURL, 21 | uploadChunkSizeInMB: properties.UploadChunkSizeInMB, 22 | uploadChunksSequentially: properties.UploadChunksSequentially, 23 | disableProgressBar: properties.DisableProgressBar, 24 | } 25 | } 26 | 27 | func (c Snapshot) GetBackendURL() string { 28 | return getStringProperty(c.backendURL) 29 | } 30 | 31 | func (c Snapshot) GetUploadChunkSizeInMB() uint64 { 32 | return getUint64Property(c.uploadChunkSizeInMB) 33 | } 34 | 35 | func (c Snapshot) GetUploadChunksSequentially() bool { 36 | return getBoolProperty(c.uploadChunksSequentially) 37 | } 38 | 39 | func (c Snapshot) GetDisableUploadProgressBar() bool { 40 | return getBoolProperty(c.disableProgressBar) 41 | } 42 | 43 | func getStringProperty(property properties.ConfigurableProperty) string { 44 | uncastedValue := getPropertyOrDefault(property) 45 | value, ok := uncastedValue.(string) 46 | if !ok { 47 | panic(fmt.Sprintf(unknownError, property.Name, uncastedValue)) 48 | } 49 | return value 50 | } 51 | 52 | func getUint64Property(property properties.ConfigurableProperty) uint64 { 53 | uncastedValue := getPropertyOrDefault(property) 54 | value, ok := uncastedValue.(uint64) 55 | if !ok { 56 | panic(fmt.Sprintf(unknownError, property.Name, uncastedValue)) 57 | } 58 | return value 59 | } 60 | 61 | func getBoolProperty(property properties.ConfigurableProperty) bool { 62 | uncastedValue := getPropertyOrDefault(property) 63 | value, ok := uncastedValue.(bool) 64 | if !ok { 65 | panic(fmt.Sprintf(unknownError, property.Name, uncastedValue)) 66 | } 67 | return value 68 | } 69 | 70 | func getPropertyOrDefault(property properties.ConfigurableProperty) interface{} { 71 | value := getPropertyWithNameOrDefaultIfInvalid(property, property.Name) 72 | if value != nil { 73 | return value 74 | } 75 | return property.DefaultValue 76 | } 77 | 78 | func getPropertyWithNameOrDefaultIfInvalid(property properties.ConfigurableProperty, name string) interface{} { 79 | propertyValue, err := getPropertyWithName(name, property.Parser) 80 | if err != nil { 81 | propertyValue = os.Getenv(name) 82 | fmt.Printf(property.ParsingFailureMessage, propertyValue, name, property.DefaultValue) 83 | return property.DefaultValue 84 | } 85 | if propertyValue != nil { 86 | fmt.Printf(property.ParsingSuccessMessage, propertyValue, name) 87 | return propertyValue 88 | } 89 | return nil 90 | } 91 | 92 | func getPropertyWithName(name string, parser properties.Parser) (interface{}, error) { 93 | propertyValue := os.Getenv(name) 94 | if propertyValue != "" { 95 | return parser.Parse(propertyValue) 96 | } 97 | return nil, nil 98 | } 99 | -------------------------------------------------------------------------------- /configuration/configuration_suite_test.go: -------------------------------------------------------------------------------- 1 | package configuration_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestUtil(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Configuration Suite") 13 | } 14 | -------------------------------------------------------------------------------- /configuration/configuration_test.go: -------------------------------------------------------------------------------- 1 | package configuration_test 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/configuration" 5 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/configuration/properties" 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 7 | . "github.com/onsi/ginkgo" 8 | . "github.com/onsi/gomega" 9 | "os" 10 | "strconv" 11 | ) 12 | 13 | var _ = Describe("Configuration", func() { 14 | 15 | BeforeEach(func() { 16 | ui.DisableTerminalOutput(true) 17 | }) 18 | 19 | Describe("GetBackendURL", func() { 20 | 21 | BeforeEach(func() { 22 | os.Unsetenv(properties.BackendURL.Name) 23 | }) 24 | 25 | Context("with a set environment variable", func() { 26 | It("should return its value", func() { 27 | backendURL := "http://my-multiapps-controller.domain.com" 28 | os.Setenv(properties.BackendURL.Name, backendURL) 29 | configurationSnapshot := configuration.NewSnapshot() 30 | Expect(configurationSnapshot.GetBackendURL()).To(Equal(backendURL)) 31 | }) 32 | }) 33 | Context("without a set environment variable", func() { 34 | It("should return an empty string", func() { 35 | configurationSnapshot := configuration.NewSnapshot() 36 | Expect(configurationSnapshot.GetBackendURL()).To(BeEmpty()) 37 | }) 38 | }) 39 | 40 | }) 41 | 42 | Describe("GetChunkSizeInMB", func() { 43 | 44 | BeforeEach(func() { 45 | os.Unsetenv(properties.UploadChunkSizeInMB.Name) 46 | }) 47 | 48 | Context("with a set environment variable", func() { 49 | Context("containing a positive integer", func() { 50 | It("should return its value", func() { 51 | uploadChunkSizeInMB := uint64(5) 52 | os.Setenv(properties.UploadChunkSizeInMB.Name, strconv.Itoa(int(uploadChunkSizeInMB))) 53 | configurationSnapshot := configuration.NewSnapshot() 54 | Expect(configurationSnapshot.GetUploadChunkSizeInMB()).To(Equal(uploadChunkSizeInMB)) 55 | }) 56 | }) 57 | Context("containing zero", func() { 58 | It("should return the default value", func() { 59 | uploadChunkSizeInMB := 0 60 | os.Setenv(properties.UploadChunkSizeInMB.Name, strconv.Itoa(uploadChunkSizeInMB)) 61 | configurationSnapshot := configuration.NewSnapshot() 62 | Expect(configurationSnapshot.GetUploadChunkSizeInMB()).To(Equal(properties.DefaultUploadChunkSizeInMB)) 63 | }) 64 | }) 65 | Context("containing a string", func() { 66 | It("should return the default value", func() { 67 | uploadChunkSizeInMB := "abc" 68 | os.Setenv(properties.UploadChunkSizeInMB.Name, uploadChunkSizeInMB) 69 | configurationSnapshot := configuration.NewSnapshot() 70 | Expect(configurationSnapshot.GetUploadChunkSizeInMB()).To(Equal(properties.DefaultUploadChunkSizeInMB)) 71 | }) 72 | }) 73 | }) 74 | Context("without a set environment variable", func() { 75 | It("should return the default value", func() { 76 | configurationSnapshot := configuration.NewSnapshot() 77 | Expect(configurationSnapshot.GetUploadChunkSizeInMB()).To(Equal(properties.DefaultUploadChunkSizeInMB)) 78 | }) 79 | }) 80 | 81 | }) 82 | 83 | }) 84 | -------------------------------------------------------------------------------- /configuration/properties/backend_url_configurable_property.go: -------------------------------------------------------------------------------- 1 | package properties 2 | 3 | var BackendURL = ConfigurableProperty{ 4 | Name: "MULTIAPPS_CONTROLLER_URL", 5 | Parser: noOpParser{}, 6 | ParsingSuccessMessage: "Attention: You've specified a custom backend URL (%s) via the environment variable \"%s\". The application listening on that URL may be outdated, contain bugs or unreleased features or may even be modified by a potentially untrused person. Use at your own risk.\n", 7 | ParsingFailureMessage: "No validation implemented for custom backend URLs. If you're seeing this message then something has gone horribly wrong.\n", 8 | DefaultValue: "", 9 | } 10 | -------------------------------------------------------------------------------- /configuration/properties/configurable_property.go: -------------------------------------------------------------------------------- 1 | package properties 2 | 3 | type ConfigurableProperty struct { 4 | Name string 5 | Parser Parser 6 | ParsingSuccessMessage string 7 | ParsingFailureMessage string 8 | DefaultValue interface{} 9 | } 10 | 11 | type Parser interface { 12 | Parse(value string) (interface{}, error) 13 | } 14 | 15 | type noOpParser struct { 16 | } 17 | 18 | func (p noOpParser) Parse(value string) (interface{}, error) { 19 | return value, nil 20 | } 21 | -------------------------------------------------------------------------------- /configuration/properties/disable_progress_bar_property.go: -------------------------------------------------------------------------------- 1 | package properties 2 | 3 | const DefaultDisableProgressBar = false 4 | 5 | var DisableProgressBar = ConfigurableProperty{ 6 | Name: "MULTIAPPS_DISABLE_UPLOAD_PROGRESS_BAR", 7 | Parser: booleanParser{}, 8 | ParsingSuccessMessage: "Attention: You've specified %v for the environment variable %s.\n", 9 | ParsingFailureMessage: "Invalid boolean value (%s) for environment variable %s. Using default value %v.\n", 10 | DefaultValue: DefaultDisableProgressBar, 11 | } 12 | -------------------------------------------------------------------------------- /configuration/properties/upload_chunk_size_configurable_property.go: -------------------------------------------------------------------------------- 1 | package properties 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | ) 7 | 8 | const DefaultUploadChunkSizeInMB = uint64(45) 9 | 10 | var UploadChunkSizeInMB = ConfigurableProperty{ 11 | Name: "MULTIAPPS_UPLOAD_CHUNK_SIZE", 12 | Parser: uploadChunkSizeParser{}, 13 | ParsingSuccessMessage: "Attention: You've specified a custom chunk size (%d MB) via the environment variable \"%s\".\n", 14 | ParsingFailureMessage: "Attention: You've specified an INVALID custom chunk size (%s) via the environment variable \"%s\". Using default: %d\n", 15 | DefaultValue: DefaultUploadChunkSizeInMB, 16 | } 17 | 18 | type uploadChunkSizeParser struct{} 19 | 20 | func (p uploadChunkSizeParser) Parse(value string) (interface{}, error) { 21 | parsedValue, err := parseUint64(value) 22 | if err != nil { 23 | return nil, err 24 | } 25 | if parsedValue == 0 { 26 | return nil, errors.New("chunk size cannot be 0") 27 | } 28 | return parsedValue, nil 29 | } 30 | 31 | func parseUint64(value string) (uint64, error) { 32 | return strconv.ParseUint(value, 10, 64) 33 | } 34 | -------------------------------------------------------------------------------- /configuration/properties/upload_chunks_sequentially_property.go: -------------------------------------------------------------------------------- 1 | package properties 2 | 3 | import "strconv" 4 | 5 | const DefaultUploadChunksSequentially = false 6 | 7 | var UploadChunksSequentially = ConfigurableProperty{ 8 | Name: "MULTIAPPS_UPLOAD_CHUNKS_SEQUENTIALLY", 9 | Parser: booleanParser{}, 10 | ParsingSuccessMessage: "Attention: You've specified %v for the environment variable %s.\n", 11 | ParsingFailureMessage: "Invalid boolean value (%s) for environment variable %s. Using default value %v.\n", 12 | DefaultValue: DefaultUploadChunksSequentially, 13 | } 14 | 15 | type booleanParser struct{} 16 | 17 | func (booleanParser) Parse(value string) (interface{}, error) { 18 | result, err := strconv.ParseBool(value) 19 | if err != nil { 20 | return false, err 21 | } 22 | return result, nil 23 | } 24 | -------------------------------------------------------------------------------- /log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | var Debug = os.Getenv("DEBUG") == "1" 9 | 10 | type Exiter interface { 11 | Exit(status int) 12 | } 13 | 14 | type DefaultExiter struct { 15 | } 16 | 17 | func (e DefaultExiter) Exit(status int) { 18 | os.Exit(status) 19 | } 20 | 21 | var exiter Exiter = DefaultExiter{} 22 | 23 | // TODO Handle concurrent access correctly 24 | func GetExiter() Exiter { 25 | return exiter 26 | } 27 | 28 | // TODO Handle concurrent access correctly 29 | func SetExiter(e Exiter) { 30 | exiter = e 31 | } 32 | 33 | func Exit(status int) { 34 | exiter.Exit(status) 35 | } 36 | 37 | func Fatal(v ...interface{}) { 38 | Print(v...) 39 | exiter.Exit(1) 40 | } 41 | 42 | func Fatalf(format string, v ...interface{}) { 43 | Printf(format, v...) 44 | exiter.Exit(1) 45 | } 46 | 47 | func Fatalln(v ...interface{}) { 48 | Println(v...) 49 | exiter.Exit(1) 50 | } 51 | 52 | func Print(v ...interface{}) { 53 | fmt.Print(v...) 54 | } 55 | 56 | func Printf(format string, v ...interface{}) { 57 | fmt.Printf(format, v...) 58 | } 59 | 60 | func Println(v ...interface{}) { 61 | fmt.Println(v...) 62 | } 63 | 64 | func Trace(v ...interface{}) { 65 | if Debug { 66 | Print(v...) 67 | } 68 | } 69 | 70 | func Tracef(format string, v ...interface{}) { 71 | if Debug { 72 | Printf(format, v...) 73 | } 74 | } 75 | 76 | func Traceln(v ...interface{}) { 77 | if Debug { 78 | Println(v...) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfoundry/multiapps-cli-plugin/98c70d6fcd96c7c4496c83cd340e7b46b588ebce/logo.png -------------------------------------------------------------------------------- /multiapps_plugin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | defaultlog "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | 11 | "code.cloudfoundry.org/cli/plugin" 12 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/commands" 13 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/log" 14 | ) 15 | 16 | // Version is the version of the CLI plugin. It is injected on linking time. 17 | var Version string = "0.0.0" 18 | 19 | // MultiappsPlugin represents a cf CLI plugin for executing operations on MTAs 20 | type MultiappsPlugin struct{} 21 | 22 | // Commands contains the commands supported by this plugin 23 | var Commands = []commands.Command{ 24 | commands.NewDeployCommand(), 25 | commands.NewBlueGreenDeployCommand(), 26 | commands.NewMtasCommand(), 27 | commands.NewDmolCommand(), 28 | commands.NewUndeployCommand(), 29 | commands.NewMtaCommand(), 30 | commands.NewMtaOperationsCommand(), 31 | commands.NewPurgeConfigCommand(), 32 | commands.NewRollbackMtaCommand(), 33 | } 34 | 35 | // Run runs this plugin 36 | func (p *MultiappsPlugin) Run(cliConnection plugin.CliConnection, args []string) { 37 | disableStdOut() 38 | if args[0] == "CLI-MESSAGE-UNINSTALL" { 39 | return 40 | } 41 | command, err := findCommand(args[0]) 42 | if err != nil { 43 | log.Fatalln(err) 44 | } 45 | command.Initialize(command.GetPluginCommand().Name, cliConnection) 46 | status := command.Execute(args[1:]) 47 | if status == commands.Failure { 48 | os.Exit(1) 49 | } 50 | } 51 | 52 | // GetMetadata returns the metadata of this plugin 53 | func (p *MultiappsPlugin) GetMetadata() plugin.PluginMetadata { 54 | metadata := plugin.PluginMetadata{ 55 | Name: "multiapps", 56 | Version: parseSemver(Version), 57 | MinCliVersion: plugin.VersionType{Major: 6, Minor: 7, Build: 0}, 58 | } 59 | for _, command := range Commands { 60 | metadata.Commands = append(metadata.Commands, command.GetPluginCommand()) 61 | } 62 | return metadata 63 | } 64 | 65 | func main() { 66 | plugin.Start(new(MultiappsPlugin)) 67 | } 68 | 69 | func disableStdOut() { 70 | defaultlog.SetFlags(0) 71 | defaultlog.SetOutput(io.Discard) 72 | } 73 | 74 | func findCommand(name string) (commands.Command, error) { 75 | for _, command := range Commands { 76 | pluginCommand := command.GetPluginCommand() 77 | if pluginCommand.Name == name || pluginCommand.Alias == name { 78 | return command, nil 79 | } 80 | } 81 | return nil, fmt.Errorf("Could not find command with name %q", name) 82 | } 83 | 84 | func parseSemver(version string) plugin.VersionType { 85 | mmb := strings.Split(version, ".") 86 | if len(mmb) != 3 { 87 | panic("invalid version: " + version) 88 | } 89 | major, _ := strconv.Atoi(mmb[0]) 90 | minor, _ := strconv.Atoi(mmb[1]) 91 | build, _ := strconv.Atoi(mmb[2]) 92 | 93 | return plugin.VersionType{ 94 | Major: major, 95 | Minor: minor, 96 | Build: build, 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /png/Slide1-11-26-19_13-28-21-253: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfoundry/multiapps-cli-plugin/98c70d6fcd96c7c4496c83cd340e7b46b588ebce/png/Slide1-11-26-19_13-28-21-253 -------------------------------------------------------------------------------- /png/Slide2-11-26-19_13-28-21-330: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfoundry/multiapps-cli-plugin/98c70d6fcd96c7c4496c83cd340e7b46b588ebce/png/Slide2-11-26-19_13-28-21-330 -------------------------------------------------------------------------------- /regen-client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GREEN_COLOUR='\033[0;32m' 4 | DEFAULT_COLOUR='\033[0m' # No Color 5 | 6 | check_dir() { 7 | if [ -d "$1" ]; then 8 | echo -e "Folder $1 already exists.\nDo you want to ${GREEN_COLOUR}overwrite${DEFAULT_COLOUR} the files? [y/n]" 9 | 10 | read answer 11 | 12 | if [ "$answer" != 'y' ] && [ "$answer" != 'Y' ] && [ "$answer" != 'yes' ] && [ "$answer" != 'YES' ]; then 13 | echo -e "Edit regen folder name and ${GREEN_COLOUR}restart${DEFAULT_COLOUR} script." 14 | exit 1 15 | fi 16 | 17 | rm -r "$1" 18 | fi 19 | 20 | echo -e "${GREEN_COLOUR}Recreating folder...${DEFAULT_COLOUR}" 21 | mkdir "$1" 22 | } 23 | 24 | go_home=$(echo ~/go) 25 | git_home=$(echo ~/git) 26 | tmp="swagger-regen" 27 | swagger_file="mtarest.yaml" 28 | swagger_file_v2="mtarest_v2.yaml" 29 | client_name="mtaclient" 30 | 31 | if [ $# -eq 0 ]; 32 | then 33 | echo "No arguments supplied, generating in dirs ${tmp} and ${tmp}-v2" 34 | elif [ "$1" ]; then 35 | tmp="$1" 36 | fi 37 | 38 | regen_folder="${go_home}/src/github.com/cloudfoundry-incubator/multiapps-cli-plugin/${tmp}" 39 | regen_folder_v2="${regen_folder}-v2" 40 | definition_file="${git_home}/multiapps-controller/com.sap.cloud.lm.sl.cf.api/src/main/resources/${swagger_file}" 41 | definition_file_v2="${git_home}/multiapps-controller/com.sap.cloud.lm.sl.cf.api/src/main/resources/${swagger_file_v2}" 42 | 43 | check_dir "${regen_folder}" 44 | check_dir "${regen_folder_v2}" 45 | 46 | echo -e "Assuming controller project is under this parent dir: ${GREEN_COLOUR}${git_home}${DEFAULT_COLOUR}" 47 | echo -e "Assuming plugin project is under this parent dir: ${GREEN_COLOUR}${go_home}${DEFAULT_COLOUR}" 48 | echo -e "Reading from\n\t${GREEN_COLOUR}${definition_file}\n\t${definition_file_v2}${DEFAULT_COLOUR}\nGenerating in \n\t${GREEN_COLOUR}${regen_folder}\n\t${regen_folder_v2}${DEFAULT_COLOUR}" 49 | 50 | cd "${git_home%/*}" 51 | mvn -f "${git_home}/multiapps-controller/" clean package -DskipTests=true -pl=com.sap.cloud.lm.sl.cf.api 52 | 53 | swagger generate client -f ${definition_file} -A http_mta -c ${client_name} -t ${regen_folder} 54 | swagger generate client -f ${definition_file_v2} -A http_mta_v2 -c "${client_name}_v2" -t ${regen_folder_v2} -------------------------------------------------------------------------------- /test_resources/commands/extDescriptor.mtaext: -------------------------------------------------------------------------------- 1 | _schema-version: "2.0.0" 2 | ID: test-mta-ext 3 | extends: test -------------------------------------------------------------------------------- /test_resources/commands/mtaArchive.mtar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfoundry/multiapps-cli-plugin/98c70d6fcd96c7c4496c83cd340e7b46b588ebce/test_resources/commands/mtaArchive.mtar -------------------------------------------------------------------------------- /test_resources/util/mtaArchiveNoDescriptor.mtar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfoundry/multiapps-cli-plugin/98c70d6fcd96c7c4496c83cd340e7b46b588ebce/test_resources/util/mtaArchiveNoDescriptor.mtar -------------------------------------------------------------------------------- /testutil/exiter.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "bytes" 5 | io_helpers "code.cloudfoundry.org/cli/cf/util/testhelpers/io" 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 7 | "strings" 8 | ) 9 | 10 | type OutputCapturer interface { 11 | CaptureOutputAndStatus(block func() int) ([]string, int) 12 | CaptureOutput(block func()) []string 13 | } 14 | 15 | type StdoutOutputCapturer struct{} 16 | 17 | func NewStdoutOutputCapturer() OutputCapturer { 18 | return &StdoutOutputCapturer{} 19 | } 20 | 21 | func (oc *StdoutOutputCapturer) CaptureOutput(block func()) []string { 22 | return io_helpers.CaptureOutput(block) 23 | } 24 | 25 | func (oc *StdoutOutputCapturer) CaptureOutputAndStatus(block func() int) ([]string, int) { 26 | var status int 27 | output := io_helpers.CaptureOutput(func() { 28 | status = block() 29 | }) 30 | return output, status 31 | } 32 | 33 | type UIOutputCapturer struct{} 34 | 35 | func NewUIOutputCapturer() OutputCapturer { 36 | return &UIOutputCapturer{} 37 | } 38 | 39 | func (oc *UIOutputCapturer) CaptureOutput(block func()) []string { 40 | bucket := new(bytes.Buffer) 41 | ui.SetOutputBucket(bucket) 42 | block() 43 | return strings.Split(strings.TrimSpace(bucket.String()), "\n") 44 | } 45 | 46 | func (oc *UIOutputCapturer) CaptureOutputAndStatus(block func() int) ([]string, int) { 47 | var status int 48 | output := oc.CaptureOutput(func() { 49 | status = block() 50 | }) 51 | return output, status 52 | } 53 | -------------------------------------------------------------------------------- /testutil/test_token_factory.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/baseclient" 5 | "github.com/go-openapi/runtime" 6 | ) 7 | 8 | // NewCustomTokenFactory represents mock of the TokenFactory 9 | func NewCustomTokenFactory(token string) baseclient.TokenFactory { 10 | return &customTokenFactory{tokenString: token} 11 | } 12 | 13 | type customTokenFactory struct { 14 | tokenString string 15 | } 16 | 17 | func (c *customTokenFactory) NewToken() (runtime.ClientAuthInfoWriter, error) { 18 | return NewCustomBearerToken(c.tokenString), nil 19 | } 20 | 21 | func (c *customTokenFactory) NewRawToken() (string, error) { 22 | return c.tokenString, nil 23 | } 24 | -------------------------------------------------------------------------------- /testutil/transport.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "net/http" 7 | 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf" 9 | "github.com/go-openapi/runtime" 10 | "github.com/go-openapi/strfmt" 11 | ) 12 | 13 | type roundTripperFunc func(*http.Request) (*http.Response, error) 14 | 15 | func (fn roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { 16 | return fn(req) 17 | } 18 | 19 | // NewCustomTransport creates a new custom transport to be used for testing 20 | func NewCustomTransport(statusCode int) *csrf.Transport { 21 | transport := roundTripperFunc(func(req *http.Request) (*http.Response, error) { 22 | var resp http.Response 23 | resp.StatusCode = statusCode 24 | resp.Header = make(http.Header) 25 | buf := bytes.NewBuffer(nil) 26 | resp.Body = io.NopCloser(buf) 27 | return &resp, nil 28 | }) 29 | return &csrf.Transport{Delegate: transport, Csrf: &csrf.CsrfTokenHelper{}} 30 | } 31 | 32 | // NewCustomBearerToken creates a new bearer token to be used for testing 33 | func NewCustomBearerToken(token string) runtime.ClientAuthInfoWriter { 34 | return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { 35 | r.SetHeaderParam("Authorization", "Bearer "+token) 36 | return nil 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /testutil/ui.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "strings" 5 | "unicode" 6 | ) 7 | 8 | func GetTableOutputLines(headers []string, rows [][]string) []string { 9 | const padding = 3 10 | var lines []string 11 | maxLen := make(map[int]int) 12 | getMaxLen(headers, rows, maxLen) 13 | lines = append(lines, getLine(headers, maxLen, padding)) 14 | for _, row := range rows { 15 | lines = append(lines, getLine(row, maxLen, padding)) 16 | } 17 | return lines 18 | } 19 | 20 | func getLine(row []string, maxLen map[int]int, padding int) string { 21 | var line string 22 | for i := range row { 23 | line = line + row[i] + strings.Repeat(" ", getSpaceCount(i, row, maxLen, padding)) 24 | } 25 | return strings.TrimRightFunc(line, unicode.IsSpace) 26 | } 27 | 28 | func getSpaceCount(i int, row []string, maxLen map[int]int, padding int) int { 29 | var count int 30 | if i < len(row)-1 { 31 | count = maxLen[i] - len(row[i]) + padding 32 | } else { 33 | count = padding 34 | } 35 | return count 36 | } 37 | 38 | func getMaxLen(headers []string, rows [][]string, maxLen map[int]int) { 39 | getRowMaxLen(headers, maxLen) 40 | for _, row := range rows { 41 | getRowMaxLen(row, maxLen) 42 | } 43 | } 44 | 45 | func getRowMaxLen(row []string, maxLen map[int]int) { 46 | for i, col := range row { 47 | if len(col) > maxLen[i] { 48 | maxLen[i] = len(col) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ui/ui.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "runtime" 8 | 9 | "code.cloudfoundry.org/cli/cf/i18n" 10 | "code.cloudfoundry.org/cli/cf/terminal" 11 | "code.cloudfoundry.org/cli/cf/trace" 12 | ) 13 | 14 | var teePrinter *terminal.TeePrinter 15 | var ui terminal.UI 16 | 17 | func init() { 18 | i18n.T = func(translationID string, args ...interface{}) string { 19 | return translationID 20 | } 21 | disableColorsIfNeeded() 22 | teePrinter = terminal.NewTeePrinter(os.Stdout) 23 | ui = terminal.NewUI(os.Stdin, os.Stdout, teePrinter, trace.NewWriterPrinter(io.Discard, false)) 24 | } 25 | 26 | func disableColorsIfNeeded() { 27 | if runtime.GOOS == "windows" { 28 | terminal.UserAskedForColors = "false" 29 | terminal.InitColorSupport() 30 | } 31 | } 32 | 33 | func SetOutputBucket(bucket io.Writer) { 34 | teePrinter.SetOutputBucket(bucket) 35 | } 36 | 37 | func ClearOutputBucket() { 38 | teePrinter.SetOutputBucket(nil) 39 | } 40 | 41 | func DisableTerminalOutput(disable bool) { 42 | teePrinter.DisableTerminalOutput(disable) 43 | } 44 | 45 | func PrintPaginator(rows []string, err error) { 46 | ui.PrintPaginator(rows, err) 47 | } 48 | 49 | func Say(message string, args ...interface{}) { 50 | ui.Say(message, args...) 51 | } 52 | 53 | func PrintCapturingNoOutput(message string, args ...interface{}) { 54 | ui.PrintCapturingNoOutput(message, args...) 55 | } 56 | 57 | func Warn(message string, args ...interface{}) { 58 | ui.Warn(message, args...) 59 | } 60 | 61 | func Ask(prompt string, args ...interface{}) (answer string) { 62 | return ui.Ask(fmt.Sprintf(prompt, args...)) 63 | } 64 | 65 | func Confirm(message string, args ...interface{}) bool { 66 | return ui.Confirm(fmt.Sprintf(message, args...)) 67 | } 68 | 69 | func Ok() { 70 | ui.Ok() 71 | } 72 | 73 | func Failed(message string, args ...interface{}) { 74 | ui.Failed(message, args...) 75 | } 76 | 77 | func LoadingIndication() { 78 | ui.LoadingIndication() 79 | } 80 | 81 | func Table(headers []string) *terminal.UITable { 82 | return ui.Table(headers) 83 | } 84 | -------------------------------------------------------------------------------- /util/archive_handler_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 8 | . "github.com/onsi/ginkgo" 9 | . "github.com/onsi/gomega" 10 | ) 11 | 12 | var _ = Describe("ArchiveHandler", func() { 13 | Describe("GetMtaDescriptorFromArchive", func() { 14 | var mtaArchiveFilePath, _ = filepath.Abs("../test_resources/commands/mtaArchive.mtar") 15 | Context("with valid mta archive", func() { 16 | It("should extract and return the id from deployment descriptor", func() { 17 | descriptor, err := util.GetMtaDescriptorFromArchive(mtaArchiveFilePath) 18 | Expect(err).To(BeZero()) 19 | Expect(descriptor.ID).To(Equal("test")) 20 | }) 21 | }) 22 | Context("with valid mta archive and no deployment descriptor provided", func() { 23 | It("should return error", func() { 24 | mtaArchiveFilePath, _ = filepath.Abs("../test_resources/util/mtaArchiveNoDescriptor.mtar") 25 | _, err := util.GetMtaDescriptorFromArchive(mtaArchiveFilePath) 26 | Expect(err).To(MatchError("Could not get a valid MTA descriptor from archive")) 27 | }) 28 | }) 29 | 30 | Context("with invalid mta archive", func() { 31 | const testMtarName = "test.mtar" 32 | var testFile *os.File 33 | BeforeEach(func() { 34 | testFile, _ = os.Create(testMtarName) 35 | mtaArchiveFilePath, _ = filepath.Abs(testMtarName) 36 | }) 37 | It("should return error for not a valid zip archive", func() { 38 | _, err := util.GetMtaDescriptorFromArchive(mtaArchiveFilePath) 39 | Expect(err).To(MatchError("zip: not a valid zip file")) 40 | }) 41 | AfterEach(func() { 42 | testFile.Close() 43 | os.Remove(testMtarName) 44 | }) 45 | }) 46 | }) 47 | }) 48 | -------------------------------------------------------------------------------- /util/builders.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "net/url" 7 | "strings" 8 | 9 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 10 | ) 11 | 12 | // ProcessBuilder a builder for models.Process instances 13 | type ProcessBuilder struct { 14 | operation models.Operation 15 | } 16 | 17 | // NewProcessBuilder creates a new process builder 18 | func NewProcessBuilder() *ProcessBuilder { 19 | return &ProcessBuilder{operation: models.Operation{Parameters: make(map[string]interface{})}} 20 | } 21 | 22 | func (pb *ProcessBuilder) ProcessType(processType string) *ProcessBuilder { 23 | pb.operation.ProcessType = processType 24 | return pb 25 | } 26 | 27 | func (pb *ProcessBuilder) Namespace(namespace string) *ProcessBuilder { 28 | pb.operation.Namespace = namespace 29 | return pb 30 | } 31 | 32 | // Parameter adds a parameter to the process if it is set 33 | func (pb *ProcessBuilder) Parameter(parameterID string, value string) *ProcessBuilder { 34 | if value != "" { 35 | pb.operation.Parameters[parameterID] = value 36 | } 37 | return pb 38 | } 39 | 40 | // SetParameterWithoutCheck sets the parameter without checking whether it is null 41 | func (pb *ProcessBuilder) SetParameterWithoutCheck(parameterID string, value string) *ProcessBuilder { 42 | pb.operation.Parameters[parameterID] = value 43 | return pb 44 | } 45 | 46 | // Build builds the process 47 | func (pb *ProcessBuilder) Build() *models.Operation { 48 | return &pb.operation 49 | } 50 | 51 | const hostAndSchemeSeparator = "://" 52 | 53 | type UriBuilder struct { 54 | host string 55 | scheme string 56 | path string 57 | } 58 | 59 | func NewUriBuilder() *UriBuilder { 60 | return &UriBuilder{host: "", scheme: "", path: ""} 61 | } 62 | 63 | func (builder *UriBuilder) SetScheme(scheme string) *UriBuilder { 64 | builder.scheme = scheme 65 | return builder 66 | } 67 | 68 | func (builder *UriBuilder) SetHost(host string) *UriBuilder { 69 | builder.host = host 70 | return builder 71 | } 72 | 73 | func (builder *UriBuilder) SetPath(path string) *UriBuilder { 74 | builder.path = path 75 | return builder 76 | } 77 | 78 | func (builder *UriBuilder) Build() (string, error) { 79 | if builder.scheme == "" || builder.host == "" { 80 | return "", fmt.Errorf("The host or scheme could not be empty") 81 | } 82 | stringBuilder := bytes.Buffer{} 83 | stringBuilder.WriteString(builder.scheme) 84 | stringBuilder.WriteString(hostAndSchemeSeparator) 85 | stringBuilder.WriteString(builder.host) 86 | stringBuilder.WriteString(getPath(builder.path)) 87 | builtUrl := stringBuilder.String() 88 | parsedUrl, err := url.Parse(builtUrl) 89 | if err != nil { 90 | return "", err 91 | } 92 | return parsedUrl.String(), nil 93 | } 94 | 95 | func getPath(path string) string { 96 | if strings.HasPrefix(path, "/") { 97 | return path 98 | } 99 | 100 | return "/" + path 101 | } 102 | -------------------------------------------------------------------------------- /util/builders_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 5 | . "github.com/onsi/ginkgo" 6 | . "github.com/onsi/gomega" 7 | ) 8 | 9 | var _ = Describe("UriBuilderTest", func() { 10 | Describe("BuildUriTest", func() { 11 | const hostName = "test-host" 12 | const scheme = "test-scheme" 13 | const path = "test-path" 14 | 15 | Context("no scheme and host are provided", func() { 16 | It("should return an error", func() { 17 | uriBuilder := util.NewUriBuilder().SetPath(path) 18 | _, err := uriBuilder.Build() 19 | 20 | Expect(err).Should(MatchError("The host or scheme could not be empty")) 21 | }) 22 | }) 23 | Context("when scheme and path are provided", func() { 24 | It("should return an error", func() { 25 | uriBuilder := util.NewUriBuilder().SetScheme(scheme).SetPath(path) 26 | _, err := uriBuilder.Build() 27 | 28 | Expect(err).Should(MatchError("The host or scheme could not be empty")) 29 | }) 30 | }) 31 | Context("when scheme, host and path are provided", func() { 32 | It("should the built uri", func() { 33 | uriBuilder := util.NewUriBuilder().SetHost(hostName).SetScheme(scheme).SetPath(path) 34 | uri, err := uriBuilder.Build() 35 | 36 | Expect(uri).To(Equal("test-scheme://test-host/test-path")) 37 | Expect(err).To(BeNil()) 38 | }) 39 | }) 40 | 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /util/cf_command_builder.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | ) 7 | 8 | // CfCommandStringBuilder ... 9 | type CfCommandStringBuilder struct { 10 | name string 11 | args bytes.Buffer 12 | opts bytes.Buffer 13 | } 14 | 15 | const longOptionPrefix = "--" 16 | const optionPrefix = "-" 17 | 18 | // NewCfCommandStringBuilder creates a new CfCommandStringBuilder 19 | func NewCfCommandStringBuilder() *CfCommandStringBuilder { 20 | return &CfCommandStringBuilder{} 21 | } 22 | 23 | // SetName sets the name of the command that will be generated from the Build method 24 | func (builder *CfCommandStringBuilder) SetName(name string) *CfCommandStringBuilder { 25 | builder.name = name 26 | return builder 27 | } 28 | 29 | // AddBooleanOption adds a short boolean option to the command that will be generated from the Build method 30 | func (builder *CfCommandStringBuilder) AddBooleanOption(option string) *CfCommandStringBuilder { 31 | return builder.addBooleanOption(option, optionPrefix) 32 | } 33 | 34 | // AddOption adds a short option to the command that will be generated from the Build method 35 | func (builder *CfCommandStringBuilder) AddOption(option, value string) *CfCommandStringBuilder { 36 | return builder.addOption(option, value, optionPrefix) 37 | } 38 | 39 | func (builder *CfCommandStringBuilder) addBooleanOption(option, prefix string) *CfCommandStringBuilder { 40 | builder.opts.WriteString(prefix) 41 | builder.opts.WriteString(option) 42 | builder.opts.WriteRune(' ') 43 | return builder 44 | } 45 | 46 | func (builder *CfCommandStringBuilder) addOption(option, value, prefix string) *CfCommandStringBuilder { 47 | builder.opts.WriteString(prefix) 48 | builder.opts.WriteString(option) 49 | builder.opts.WriteRune(' ') 50 | builder.opts.WriteString(value) 51 | builder.opts.WriteRune(' ') 52 | return builder 53 | } 54 | 55 | // AddLongBooleanOption adds a long boolean option to the command that will be generated from the Build method 56 | func (builder *CfCommandStringBuilder) AddLongBooleanOption(option string) *CfCommandStringBuilder { 57 | return builder.addBooleanOption(option, longOptionPrefix) 58 | } 59 | 60 | // AddLongOption adds a long option to the command that will be generated from the Build method 61 | func (builder *CfCommandStringBuilder) AddLongOption(option, value string) *CfCommandStringBuilder { 62 | return builder.addOption(option, value, longOptionPrefix) 63 | } 64 | 65 | // AddArgument adds an argument to the command that will be generated from the Build method 66 | func (builder *CfCommandStringBuilder) AddArgument(argument string) *CfCommandStringBuilder { 67 | builder.args.WriteString(argument) 68 | builder.args.WriteRune(' ') 69 | return builder 70 | } 71 | 72 | // Build generates a command string, in which the arguments always preceed the options 73 | func (builder *CfCommandStringBuilder) Build() string { 74 | var commandBuilder bytes.Buffer 75 | 76 | commandBuilder.WriteString("cf ") 77 | commandBuilder.WriteString(builder.name) 78 | commandBuilder.WriteRune(' ') 79 | commandBuilder.WriteString(builder.args.String()) 80 | commandBuilder.WriteString(builder.opts.String()) 81 | 82 | return strings.Trim(commandBuilder.String(), " ") 83 | } 84 | -------------------------------------------------------------------------------- /util/cf_command_builder_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | . "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | var _ = Describe("CfCommandBuilder", func() { 11 | Describe("Build", func() { 12 | Context("with valid argument and options", func() { 13 | It("should return a valid command", func() { 14 | commandBuilder := NewCfCommandStringBuilder() 15 | commandBuilder.SetName("deploy") 16 | commandBuilder.AddArgument("jobscheduler.mtar") 17 | commandBuilder.AddBooleanOption("f") 18 | commandBuilder.AddOption("t", "100") 19 | commandBuilder.AddLongBooleanOption("no-start") 20 | commandBuilder.AddOption("p", "XSA") 21 | commandBuilder.AddLongOption("schema-version", "3") 22 | Expect(commandBuilder.Build()).To(Equal("cf deploy jobscheduler.mtar -f -t 100 --no-start -p XSA --schema-version 3")) 23 | }) 24 | }) 25 | Context("with just options and no arguments", func() { 26 | It("should return a valid command", func() { 27 | commandBuilder := NewCfCommandStringBuilder() 28 | commandBuilder.SetName("deploy") 29 | commandBuilder.AddOption("i", "12345") 30 | commandBuilder.AddOption("a", "abort") 31 | Expect(commandBuilder.Build()).To(Equal("cf deploy -i 12345 -a abort")) 32 | }) 33 | }) 34 | Context("with just arguments and no options", func() { 35 | It("should return a valid command", func() { 36 | commandBuilder := NewCfCommandStringBuilder() 37 | commandBuilder.SetName("deploy") 38 | commandBuilder.AddArgument("jobscheduler1.mtar") 39 | commandBuilder.AddArgument("jobscheduler2.mtar") 40 | Expect(commandBuilder.Build()).To(Equal("cf deploy jobscheduler1.mtar jobscheduler2.mtar")) 41 | }) 42 | }) 43 | }) 44 | }) 45 | -------------------------------------------------------------------------------- /util/cf_command_options_util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | ) 7 | 8 | func CombineFullAndShortParameters(fullParameter string, shortParameter string) string { 9 | return GetShortOption(fullParameter) + ", -" + shortParameter 10 | } 11 | 12 | //GetShortOption ... 13 | func GetShortOption(option string) string { 14 | var opt bytes.Buffer 15 | opt.WriteString(optionPrefix) 16 | opt.WriteString(option) 17 | return opt.String() 18 | } 19 | 20 | func DiscardIfEmpty(value string) *string { 21 | if len(value) > 0 { 22 | return &value 23 | } else { 24 | return nil 25 | } 26 | } 27 | 28 | func TrimAndDiscardIfEmpty(value string) *string { 29 | var trimmedValue = strings.TrimSpace(value) 30 | if len(trimmedValue) > 0 { 31 | return &trimmedValue 32 | } else { 33 | return nil 34 | } 35 | } 36 | 37 | func NamespaceInfoTextIfApplicable(namespace string) string { 38 | if DiscardIfEmpty(namespace) == nil { 39 | return "" 40 | } 41 | 42 | return " with namespace " + namespace 43 | } 44 | -------------------------------------------------------------------------------- /util/cf_command_options_util_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | . "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | var _ = Describe("CfCommandOptionsUtil", func() { 11 | Describe("DiscardIfEmpty", func() { 12 | Context("with regular string value", func() { 13 | It("should return the value as is", func() { 14 | value := "some value" 15 | Expect(DiscardIfEmpty(value)).To(Equal(&value)) 16 | }) 17 | }) 18 | Context("with string value with only whitespace", func() { 19 | It("should return the value as is", func() { 20 | value := " " 21 | Expect(DiscardIfEmpty(value)).To(Equal(&value)) 22 | }) 23 | }) 24 | Context("with empty string value", func() { 25 | It("should return nil", func() { 26 | Expect(TrimAndDiscardIfEmpty("")).To(BeNil()) 27 | }) 28 | }) 29 | }) 30 | Describe("TrimAndDiscardIfEmpty", func() { 31 | expected_value := "some value" 32 | 33 | Context("with regular string value", func() { 34 | It("should return the value as is", func() { 35 | Expect(TrimAndDiscardIfEmpty("some value")).To(Equal(&expected_value)) 36 | }) 37 | }) 38 | Context("with string value with leading and trailing whitespace", func() { 39 | It("should trim the value", func() { 40 | Expect(TrimAndDiscardIfEmpty(" some value ")).To(Equal(&expected_value)) 41 | }) 42 | }) 43 | Context("with empty string value", func() { 44 | It("should return nil", func() { 45 | Expect(TrimAndDiscardIfEmpty("")).To(BeNil()) 46 | }) 47 | }) 48 | Context("with only whitespace in value", func() { 49 | It("should return nil", func() { 50 | Expect(TrimAndDiscardIfEmpty(" ")).To(BeNil()) 51 | }) 52 | }) 53 | }) 54 | }) 55 | -------------------------------------------------------------------------------- /util/cf_context.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "code.cloudfoundry.org/cli/cf/terminal" 5 | "code.cloudfoundry.org/cli/plugin" 6 | plugin_models "code.cloudfoundry.org/cli/plugin/models" 7 | "fmt" 8 | ) 9 | 10 | type CloudFoundryContext struct { 11 | cliConnection plugin.CliConnection 12 | } 13 | 14 | func NewCloudFoundryContext(cliConnection plugin.CliConnection) CloudFoundryContext { 15 | return CloudFoundryContext{cliConnection: cliConnection} 16 | } 17 | 18 | // GetOrg gets the current org from the CLI connection 19 | func (c *CloudFoundryContext) GetOrg() (plugin_models.Organization, error) { 20 | org, err := c.cliConnection.GetCurrentOrg() 21 | if err != nil { 22 | return plugin_models.Organization{}, fmt.Errorf("Could not get current org: %s", err) 23 | } 24 | if org.Name == "" { 25 | return plugin_models.Organization{}, fmt.Errorf("No org and space targeted, use %q to target an org and a space", terminal.CommandColor("cf target -o ORG -s SPACE")) 26 | } 27 | return org, nil 28 | } 29 | 30 | // GetSpace gets the current space from the CLI connection 31 | func (c *CloudFoundryContext) GetSpace() (plugin_models.Space, error) { 32 | space, err := c.cliConnection.GetCurrentSpace() 33 | if err != nil { 34 | return plugin_models.Space{}, fmt.Errorf("Could not get current space: %s", err) 35 | } 36 | 37 | if space.Name == "" || space.Guid == "" { 38 | return plugin_models.Space{}, fmt.Errorf("No space targeted, use %q to target a space", terminal.CommandColor("cf target -s SPACE")) 39 | } 40 | return space, nil 41 | } 42 | 43 | // GetUsername gets the username from the CLI connection 44 | func (c *CloudFoundryContext) GetUsername() (string, error) { 45 | username, err := c.cliConnection.Username() 46 | if err != nil { 47 | return "", fmt.Errorf("Could not get username: %s", err) 48 | } 49 | if username == "" { 50 | return "", fmt.Errorf("Not logged in. Use %q to log in.", terminal.CommandColor("cf login")) 51 | } 52 | return username, nil 53 | } 54 | -------------------------------------------------------------------------------- /util/cf_context_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | 6 | "code.cloudfoundry.org/cli/cf/terminal" 7 | 8 | plugin_fakes "code.cloudfoundry.org/cli/plugin/pluginfakes" 9 | cli_fakes "github.com/cloudfoundry-incubator/multiapps-cli-plugin/cli/fakes" 10 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 11 | . "github.com/onsi/ginkgo" 12 | . "github.com/onsi/gomega" 13 | ) 14 | 15 | var _ = Describe("CloudFoundryContext", func() { 16 | const ( 17 | org = "test-org" 18 | space = "test-space" 19 | user = "test-user" 20 | ) 21 | 22 | var fakeCliConnection *plugin_fakes.FakeCliConnection 23 | 24 | BeforeEach(func() { 25 | ui.DisableTerminalOutput(true) 26 | fakeCliConnection = cli_fakes.NewFakeCliConnectionBuilder(). 27 | CurrentOrg("test-org-guid", org, nil). 28 | CurrentSpace("test-space-guid", space, nil). 29 | Username(user, nil). 30 | AccessToken("bearer test-token", nil).Build() 31 | }) 32 | 33 | Describe("GetOrg", func() { 34 | Context("with valid org returned by the CLI connection", func() { 35 | It("should not exit or report any errors", func() { 36 | cfContext := NewCloudFoundryContext(fakeCliConnection) 37 | org, err := cfContext.GetOrg() 38 | Expect(err).ShouldNot(HaveOccurred()) 39 | Expect(org).To(Equal(org)) 40 | }) 41 | }) 42 | Context("with no org returned by the CLI connection", func() { 43 | It("should print an error and exit with a non-zero status", func() { 44 | fakeCliConnection := cli_fakes.NewFakeCliConnectionBuilder(). 45 | CurrentOrg("", "", nil).Build() 46 | cfContext := NewCloudFoundryContext(fakeCliConnection) 47 | _, err := cfContext.GetOrg() 48 | Expect(err).To(MatchError(fmt.Errorf("No org and space targeted, use %q to target an org and a space", terminal.CommandColor("cf target -o ORG -s SPACE")))) 49 | }) 50 | }) 51 | }) 52 | 53 | Describe("GetSpace", func() { 54 | Context("with valid space returned by the CLI connection", func() { 55 | It("should not exit or report any errors", func() { 56 | cfContext := NewCloudFoundryContext(fakeCliConnection) 57 | space, err := cfContext.GetSpace() 58 | Expect(err).ShouldNot(HaveOccurred()) 59 | Expect(space).To(Equal(space)) 60 | }) 61 | }) 62 | Context("with no space returned by the CLI connection", func() { 63 | It("should print an error and exit with a non-zero status", func() { 64 | fakeCliConnection := cli_fakes.NewFakeCliConnectionBuilder(). 65 | CurrentSpace("", "", nil).Build() 66 | cfContext := NewCloudFoundryContext(fakeCliConnection) 67 | _, err := cfContext.GetSpace() 68 | Expect(err).To(MatchError(fmt.Errorf("No space targeted, use %q to target a space", terminal.CommandColor("cf target -s SPACE")))) 69 | }) 70 | }) 71 | }) 72 | 73 | Describe("GetUsername", func() { 74 | Context("with valid username returned by the CLI connection", func() { 75 | It("should not exit or report any errors", func() { 76 | cfContext := NewCloudFoundryContext(fakeCliConnection) 77 | user, err := cfContext.GetUsername() 78 | Expect(err).ShouldNot(HaveOccurred()) 79 | Expect(user).To(Equal(user)) 80 | }) 81 | }) 82 | Context("with no space returned by the CLI connection", func() { 83 | It("should print an error and exit with a non-zero status", func() { 84 | fakeCliConnection := cli_fakes.NewFakeCliConnectionBuilder(). 85 | Username("", nil).Build() 86 | cfContext := NewCloudFoundryContext(fakeCliConnection) 87 | _, err := cfContext.GetUsername() 88 | Expect(err).To(MatchError(fmt.Errorf("Not logged in. Use %q to log in.", terminal.CommandColor("cf login")))) 89 | }) 90 | }) 91 | }) 92 | }) 93 | -------------------------------------------------------------------------------- /util/cf_target.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import plugin_models "code.cloudfoundry.org/cli/plugin/models" 4 | 5 | type CloudFoundryTarget struct { 6 | Org plugin_models.Organization 7 | Space plugin_models.Space 8 | Username string 9 | } 10 | 11 | func NewCFTarget(org plugin_models.Organization, space plugin_models.Space, username string) CloudFoundryTarget { 12 | return CloudFoundryTarget{ 13 | Org: org, 14 | Space: space, 15 | Username: username, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /util/deploy_service_url_calculator.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "code.cloudfoundry.org/cli/plugin" 5 | "fmt" 6 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/configuration" 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/ui" 8 | "strings" 9 | ) 10 | 11 | const deployServiceHost = "deploy-service" 12 | 13 | type DeployServiceURLCalculator interface { 14 | ComputeDeployServiceURL(cmdOption string) (string, error) 15 | } 16 | 17 | type deployServiceURLCalculatorImpl struct { 18 | cliConn plugin.CliConnection 19 | } 20 | 21 | func NewDeployServiceURLCalculator(cliConn plugin.CliConnection) DeployServiceURLCalculator { 22 | return deployServiceURLCalculatorImpl{cliConn: cliConn} 23 | } 24 | 25 | func (c deployServiceURLCalculatorImpl) ComputeDeployServiceURL(cmdOption string) (string, error) { 26 | if cmdOption != "" { 27 | ui.Say(fmt.Sprintf("**Attention: You've specified a custom Deploy Service URL (%s) via the command line option 'u'. "+ 28 | "The application listening on that URL may be outdated, contain bugs or unreleased features or may even be modified by a potentially untrused person. Use at your own risk.**\n", cmdOption)) 29 | return cmdOption, nil 30 | } 31 | 32 | urlFromEnv := configuration.NewSnapshot().GetBackendURL() 33 | if urlFromEnv != "" { 34 | return urlFromEnv, nil 35 | } 36 | 37 | cfApi, _ := c.cliConn.ApiEndpoint() 38 | domainSeparatorIndex := strings.IndexByte(cfApi, '.') 39 | domain := cfApi[domainSeparatorIndex+1:] 40 | 41 | return deployServiceHost + "." + domain, nil 42 | } 43 | -------------------------------------------------------------------------------- /util/digest.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "crypto/md5" 5 | "crypto/sha1" 6 | "crypto/sha256" 7 | "crypto/sha512" 8 | "encoding/hex" 9 | "fmt" 10 | "hash" 11 | "io" 12 | "os" 13 | "strings" 14 | ) 15 | 16 | // ComputeFileChecksum computes the checksum of the specified file based on the specified algorithm 17 | func ComputeFileChecksum(filePath, algorithm string) (string, error) { 18 | var hasher hash.Hash 19 | switch strings.ToUpper(algorithm) { 20 | case "MD5": 21 | hasher = md5.New() 22 | case "SHA1": 23 | hasher = sha1.New() 24 | case "SHA256": 25 | hasher = sha256.New() 26 | case "SHA512": 27 | hasher = sha512.New() 28 | default: 29 | return "", fmt.Errorf("Unsupported digest algorithm %q", algorithm) 30 | } 31 | 32 | file, err := os.Open(filePath) 33 | if err != nil { 34 | return "", err 35 | } 36 | defer file.Close() 37 | 38 | _, err = io.Copy(hasher, file) 39 | if err != nil { 40 | return "", err 41 | } 42 | return hex.EncodeToString(hasher.Sum(nil)), nil 43 | } 44 | -------------------------------------------------------------------------------- /util/digest_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/testutil" 8 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 9 | 10 | . "github.com/onsi/ginkgo" 11 | ) 12 | 13 | var _ = Describe("Digest", func() { 14 | 15 | Describe("ComputeFileChecksum", func() { 16 | const testFileName = "test-file.txt" 17 | 18 | var testFilePath string 19 | var testFile *os.File 20 | 21 | BeforeEach(func() { 22 | testFile, _ = os.Create(testFileName) 23 | testFilePath, _ = filepath.Abs(testFileName) 24 | }) 25 | 26 | Context("with an unsupported digest algorithm", func() { 27 | It("should return an error", func() { 28 | digest, err := util.ComputeFileChecksum(testFilePath, "unsupported-algorithm-name") 29 | testutil.ExpectErrorAndZeroResult(err, digest) 30 | }) 31 | }) 32 | 33 | Context("with a supported digest algorithm and an empty file", func() { 34 | It("should return the digest of the file", func() { 35 | digest, err := util.ComputeFileChecksum(testFilePath, "MD5") 36 | testutil.ExpectNoErrorAndResult(err, digest, "d41d8cd98f00b204e9800998ecf8427e") 37 | }) 38 | }) 39 | 40 | Context("with a supported digest algorithm and a non-empty file", func() { 41 | It("should calculate the digest of the file and exit with zero status", func() { 42 | const testFileContent = "test file content" 43 | os.WriteFile(testFile.Name(), []byte(testFileContent), 0644) 44 | digest, err := util.ComputeFileChecksum(testFilePath, "SHA1") 45 | testutil.ExpectNoErrorAndResult(err, digest, "9032bbc224ed8b39183cb93b9a7447727ce67f9d") 46 | }) 47 | }) 48 | 49 | AfterEach(func() { 50 | testFile.Close() 51 | os.Remove(testFileName) 52 | }) 53 | }) 54 | }) 55 | -------------------------------------------------------------------------------- /util/fakes/fake_deploy_service_url_calculator.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 4 | 5 | type deployServiceURLFakeCalculatorImpl struct { 6 | deployServiceURL string 7 | } 8 | 9 | func NewDeployServiceURLFakeCalculator(deployServiceURL string) util.DeployServiceURLCalculator { 10 | return deployServiceURLFakeCalculatorImpl{deployServiceURL: deployServiceURL} 11 | } 12 | 13 | func (c deployServiceURLFakeCalculatorImpl) ComputeDeployServiceURL(cmdOption string) (string, error) { 14 | if cmdOption != "" { 15 | return cmdOption, nil 16 | } 17 | return c.deployServiceURL, nil 18 | } 19 | -------------------------------------------------------------------------------- /util/fakes/fake_http_simple_executor.go: -------------------------------------------------------------------------------- 1 | package fakes 2 | 3 | import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/util" 4 | 5 | type fakeHttpGetExecutor struct { 6 | exchanges map[string]int 7 | } 8 | 9 | func NewFakeHttpGetExecutor(exchanges map[string]int) util.HttpSimpleGetExecutor { 10 | return &fakeHttpGetExecutor{exchanges: exchanges} 11 | } 12 | 13 | func (f fakeHttpGetExecutor) ExecuteGetRequest(url string) (int, error) { 14 | return f.exchanges[url], nil 15 | } 16 | -------------------------------------------------------------------------------- /util/file_splitter.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "math" 7 | "os" 8 | "path/filepath" 9 | "strconv" 10 | 11 | "github.com/cloudfoundry-incubator/multiapps-cli-plugin/configuration/properties" 12 | "github.com/pborman/uuid" 13 | ) 14 | 15 | const MaxFileChunkCount = 50 16 | 17 | func generateHash() string { 18 | return uuid.New() 19 | } 20 | 21 | // SplitFile ... 22 | func SplitFile(filePath string, fileChunkSizeInMB uint64) ([]*os.File, error) { 23 | if fileChunkSizeInMB == 0 { 24 | return openSingleFile(filePath) 25 | } 26 | 27 | file, err := os.Open(filePath) 28 | if err != nil { 29 | return nil, err 30 | } 31 | defer file.Close() 32 | 33 | fileInfo, err := file.Stat() 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | var fileSize = uint64(fileInfo.Size()) 39 | var fileChunkSize = toBytes(fileChunkSizeInMB) 40 | 41 | // calculate total number of parts the file will be chunked into 42 | totalPartsNum := uint64(math.Ceil(float64(fileSize) / float64(fileChunkSize))) 43 | if totalPartsNum <= 1 { 44 | return openSingleFile(filePath) 45 | } 46 | 47 | partsTempDir := filepath.Join(os.TempDir(), generateHash()) 48 | errCreatingTempDir := os.MkdirAll(partsTempDir, os.ModePerm) 49 | if errCreatingTempDir != nil { 50 | return nil, errCreatingTempDir 51 | } 52 | 53 | baseFileName := filepath.Base(filePath) 54 | var fileParts []*os.File 55 | 56 | for i := uint64(0); i < totalPartsNum; i++ { 57 | filePartName := baseFileName + ".part." + strconv.FormatUint(i, 10) 58 | tempFile := filepath.Join(partsTempDir, filePartName) 59 | filePart, err := os.Create(tempFile) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | partSize := int64(minUint64(fileChunkSize, fileSize-i*fileChunkSize)) 65 | _, err = io.CopyN(filePart, file, partSize) 66 | if err != nil { 67 | filePart.Close() 68 | return nil, err 69 | } 70 | 71 | filePart.Seek(0, io.SeekStart) 72 | fileParts = append(fileParts, filePart) 73 | } 74 | return fileParts, nil 75 | } 76 | 77 | func openSingleFile(path string) ([]*os.File, error) { 78 | f, err := os.Open(path) 79 | return []*os.File{f}, err 80 | } 81 | 82 | // ValidateChunkSize validate the chunk size 83 | func ValidateChunkSize(filePath string, fileChunkSizeInMB uint64) error { 84 | if fileChunkSizeInMB == 0 { 85 | return nil 86 | } 87 | 88 | if fileChunkSizeInMB == properties.DefaultUploadChunkSizeInMB { 89 | return nil 90 | } 91 | 92 | fileInfo, err := os.Stat(filePath) 93 | if err != nil { 94 | return err 95 | } 96 | 97 | var fileSize = uint64(fileInfo.Size()) 98 | var fileSizeInMb = toMegabytes(fileSize) 99 | 100 | var minFileChunkSizeInMb = uint64(math.Ceil(float64(fileSizeInMb) / float64(MaxFileChunkCount))) 101 | 102 | if fileChunkSizeInMB < minFileChunkSizeInMb { 103 | return fmt.Errorf("The specified chunk size (%d MB) is below the minimum chunk size (%d MB) for an archive with a size of %d MBs", fileChunkSizeInMB, minFileChunkSizeInMb, fileSizeInMb) 104 | } 105 | return nil 106 | } 107 | 108 | func minUint64(a, b uint64) uint64 { 109 | if a < b { 110 | return a 111 | } 112 | return b 113 | } 114 | 115 | func toBytes(mb uint64) uint64 { 116 | return mb * 1024 * 1024 117 | } 118 | 119 | func toMegabytes(bytes uint64) uint64 { 120 | return bytes / 1024 / 1024 121 | } 122 | -------------------------------------------------------------------------------- /util/http_util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type HttpSimpleGetExecutor interface { 8 | ExecuteGetRequest(url string) (int, error) 9 | } 10 | 11 | type SimpleGetExecutor struct { 12 | } 13 | 14 | func NewSimpleGetExecutor() SimpleGetExecutor { 15 | return SimpleGetExecutor{} 16 | } 17 | 18 | func (executor SimpleGetExecutor) ExecuteGetRequest(url string) (int, error) { 19 | resp, err := http.Get(url) 20 | if err != nil { 21 | return -1, err 22 | } 23 | defer resp.Body.Close() 24 | return resp.StatusCode, nil 25 | } 26 | -------------------------------------------------------------------------------- /util/mta_deployment_descriptor.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | type MtaDeploymentDescriptor struct { 4 | SchemaVersion string `yaml:"_schema-version,omitempty"` 5 | ID string `yaml:"ID,omitempty"` 6 | Version string `yaml:"version,omitempty"` 7 | Modules []Module `yaml:"modules,omitempty"` 8 | Resources []Resource `yaml:"resources,omitempty"` 9 | } 10 | 11 | type Module struct { 12 | Name string `yaml:"name"` 13 | Type string `yaml:"type"` 14 | Path string `yaml:"path"` 15 | RequiredDependencies []RequiredDependency `yaml:"requires,omitempty"` 16 | } 17 | 18 | type Resource struct { 19 | Name string `yaml:"name"` 20 | Type string `yaml:"type"` 21 | Parameters map[string]interface{} `yaml:"parameters,omitempty"` 22 | } 23 | 24 | type RequiredDependency struct { 25 | Name string `yaml:"name"` 26 | Parameters map[string]interface{} `yaml:"parameters,omitempty"` 27 | } 28 | -------------------------------------------------------------------------------- /util/mta_version_handler.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/models" 4 | 5 | const unknownMtaVersion string = "0.0.0-unknown" 6 | 7 | // GetMtaVersionAsString returns an MTA's version as a string or "?" if the version is unknown. 8 | func GetMtaVersionAsString(mta *models.Mta) string { 9 | return getDefaultIfUnknown(mta.Metadata.Version) 10 | } 11 | 12 | func getDefaultIfUnknown(version string) string { 13 | if version != unknownMtaVersion { 14 | return version 15 | } 16 | return "?" 17 | } 18 | -------------------------------------------------------------------------------- /util/named_read_seeker.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "io" 4 | 5 | type NamedReadSeeker interface { 6 | io.ReadSeeker 7 | Name() string 8 | } 9 | -------------------------------------------------------------------------------- /util/util_suite_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestUtil(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Utilities Suite") 13 | } 14 | --------------------------------------------------------------------------------