├── .bumpversion.toml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dco.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── codeql.yml │ ├── docs.yml │ └── test.yml ├── .gitignore ├── .golangci.yml ├── .releaserc ├── .secrets.baseline ├── .whitesource ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Jenkinsfile ├── KNOWN_ISSUES.md ├── LICENSE ├── README.md ├── SECURITY.md ├── auth ├── auth_suite_test.go ├── couchdb_session_authenticator.go ├── couchdb_session_authenticator_test.go ├── session.go └── session_test.go ├── base ├── base_suite_test.go ├── cloudant_base.go ├── cloudant_base_test.go ├── error_response_transport.go └── testdata │ └── my-credentials.env ├── cloudantv1 ├── cloudant_v1.go ├── cloudant_v1_integration_test.go ├── cloudant_v1_suite_test.go └── cloudant_v1_test.go ├── common ├── common_suite_test.go ├── headers.go ├── headers_test.go └── version.go ├── config └── header-template.txt ├── examples ├── README.md └── snippets │ ├── deleteAttachment │ └── example_request.go │ ├── deleteDatabase │ └── example_request.go │ ├── deleteDesignDocument │ └── example_request.go │ ├── deleteDocument │ └── example_request.go │ ├── deleteIndex │ └── example_request.go │ ├── deleteLocalDocument │ └── example_request.go │ ├── deleteReplicationDocument │ └── example_request.go │ ├── getActiveTasks │ └── example_request.go │ ├── getActivityTrackerEvents │ └── example_request.go │ ├── getAllDbs │ └── example_request.go │ ├── getAttachment │ └── example_request.go │ ├── getCapacityThroughputInformation │ └── example_request.go │ ├── getCorsInformation │ └── example_request.go │ ├── getCurrentThroughputInformation │ └── example_request.go │ ├── getDatabaseInformation │ └── example_request.go │ ├── getDbUpdates │ └── example_request.go │ ├── getDesignDocument │ └── example_request.go │ ├── getDesignDocumentInformation │ └── example_request.go │ ├── getDocument │ └── example_request.go │ ├── getDocumentShardsInfo │ └── example_request.go │ ├── getIndexesInformation │ └── example_request.go │ ├── getLocalDocument │ └── example_request.go │ ├── getMembershipInformation │ └── example_request.go │ ├── getPartitionInformation │ └── example_request.go │ ├── getReplicationDocument │ └── example_request.go │ ├── getSchedulerDocs │ └── example_request.go │ ├── getSchedulerDocument │ └── example_request.go │ ├── getSchedulerJob │ └── example_request.go │ ├── getSchedulerJobs │ └── example_request.go │ ├── getSearchInfo │ └── example_request.go │ ├── getSecurity │ └── example_request.go │ ├── getServerInformation │ └── example_request.go │ ├── getSessionInformation │ └── example_request.go │ ├── getShardsInformation │ └── example_request.go │ ├── getUpInformation │ └── example_request.go │ ├── getUuids │ └── example_request.go │ ├── go.mod │ ├── headAttachment │ └── example_request.go │ ├── headDatabase │ └── example_request.go │ ├── headDesignDocument │ └── example_request.go │ ├── headDocument │ └── example_request.go │ ├── headReplicationDocument │ └── example_request.go │ ├── headSchedulerJob │ └── example_request.go │ ├── postActivityTrackerEvents │ └── example_request.go │ ├── postAllDocs │ ├── example_request.go │ └── example_request_as_a_stream.go │ ├── postAllDocsQueries │ └── example_request.go │ ├── postApiKeys │ └── example_request.go │ ├── postBulkDocs │ ├── example_request_as_a_stream.go │ ├── example_request_create_documents.go │ └── example_request_delete_documents.go │ ├── postBulkGet │ ├── alternative_example_request_for_atts_since.go │ ├── alternative_example_request_for_open_revs_all.go │ └── example_request.go │ ├── postChanges │ ├── example_request.go │ └── example_request_as_a_stream.go │ ├── postDbsInfo │ └── example_request.go │ ├── postDesignDocs │ └── example_request.go │ ├── postDesignDocsQueries │ └── example_request.go │ ├── postDocument │ └── example_request.go │ ├── postExplain │ └── example_request.go │ ├── postFind │ ├── example_request_for_json_index_type.go │ └── example_request_for_text_index_type.go │ ├── postIndex │ ├── example_request_using_json_type_index.go │ └── example_request_using_text_type_index.go │ ├── postPartitionAllDocs │ └── example_request.go │ ├── postPartitionExplain │ └── example_request.go │ ├── postPartitionFind │ └── example_request.go │ ├── postPartitionSearch │ └── example_request.go │ ├── postPartitionView │ └── example_request.go │ ├── postRevsDiff │ └── example_request.go │ ├── postSearch │ └── example_request.go │ ├── postSearchAnalyze │ └── example_request.go │ ├── postView │ └── example_request.go │ ├── postViewQueries │ └── example_request.go │ ├── putAttachment │ └── example_request.go │ ├── putCapacityThroughputConfiguration │ └── example_request.go │ ├── putCloudantSecurity │ └── example_request.go │ ├── putCorsConfiguration │ └── example_request.go │ ├── putDatabase │ └── example_request.go │ ├── putDesignDocument │ └── example_request.go │ ├── putDocument │ └── example_request.go │ ├── putLocalDocument │ └── example_request.go │ ├── putReplicationDocument │ └── example_request.go │ └── putSecurity │ └── example_request.go ├── features ├── changes_follower.go ├── changes_follower_suite_test.go ├── changes_follower_test.go └── changes_follower_test_fixtures_test.go ├── go.mod ├── go.sum ├── scripts ├── publish_buildinfo.sh ├── setup_couch.sh └── setup_wiremock.sh ├── stubs ├── gen-its-mappings.json └── mappings.json └── test └── examples ├── output ├── create_db_and_doc.txt ├── delete_doc.txt ├── get_info_from_existing_database.txt └── update_doc.txt └── src ├── changes_follower ├── go.mod ├── initialize.go ├── start.go ├── start_and_process.go ├── start_one_off.go ├── start_one_off_and_process.go └── stop.go ├── create_db_and_doc └── create_db_and_doc.go ├── delete_doc └── delete_doc.go ├── get_info_from_existing_database └── get_info_from_existing_database.go └── update_doc └── update_doc.go /.bumpversion.toml: -------------------------------------------------------------------------------- 1 | [tool.bumpversion] 2 | current_version = "0.10.3" 3 | commit = true 4 | message = "Update version {current_version} -> {new_version} [skip ci]" 5 | 6 | [[tool.bumpversion.files]] 7 | filename = "common/version.go" 8 | search = "const Version = \"{current_version}\"" 9 | replace = "const Version = \"{new_version}\"" 10 | 11 | [[tool.bumpversion.files]] 12 | filename = "README.md" 13 | search = "{current_version}" 14 | replace = "{new_version}" 15 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Common files: 2 | .github/CODEOWNERS @IBM/cloudant-sdks 3 | .github/ISSUE_TEMPLATE/bug_report.md @IBM/cloudant-sdks 4 | .github/ISSUE_TEMPLATE/feature_request.md @IBM/cloudant-sdks 5 | .github/dco.yml @IBM/cloudant-sdks 6 | .github/dependabot.yml @IBM/cloudant-sdks 7 | .github/pull_request_template.md @IBM/cloudant-sdks 8 | .whitesource @IBM/cloudant-sdks 9 | CODE_OF_CONDUCT.md @IBM/cloudant-sdks 10 | CONTRIBUTING.md @IBM/cloudant-sdks 11 | Jenkinsfile @IBM/cloudant-sdks 12 | KNOWN_ISSUES.md @IBM/cloudant-sdks 13 | LICENSE @IBM/cloudant-sdks 14 | README.md @IBM/cloudant-sdks 15 | SECURITY.md @IBM/cloudant-sdks 16 | scripts/publish_buildinfo.sh @IBM/cloudant-sdks 17 | scripts/setup_couch.sh @IBM/cloudant-sdks 18 | scripts/setup_wiremock.sh @IBM/cloudant-sdks 19 | stubs/gen-its-mappings.json @IBM/cloudant-sdks 20 | stubs/mappings.json @IBM/cloudant-sdks 21 | 22 | # Generated code files: 23 | 24 | cloudantv1/cloudant_v1.go @IBM/cloudant-sdks 25 | cloudantv1/cloudant_v1_suite_test.go @IBM/cloudant-sdks 26 | cloudantv1/cloudant_v1_test.go @IBM/cloudant-sdks 27 | 28 | # Version files: 29 | 30 | common/version.go @IBM/cloudant-sdks 31 | 32 | # Examples files: 33 | 34 | /examples/ @IBM/cloudant-sdks 35 | 36 | .bumpversion.cfg @IBM/cloudant-sdks 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a bug report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | 13 | **To Reproduce** 14 | 15 | 16 | **Expected behavior** 17 | 18 | 19 | **Screenshots** 20 | 21 | 22 | **Must gather (please complete the following information):** 23 | - SDK Version [e.g. 1.2.1] 24 | - Go Version [e.g. Go 1.23] 25 | - Name of service that you're trying to use (if applicable) 26 | - Name of operation that you're trying to invoke (if applicable) 27 | 28 | **Additional context** 29 | 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | **Describe the solution you'd like** 14 | 15 | 16 | **Describe alternatives you've considered** 17 | 18 | 19 | **Additional context** 20 | 21 | -------------------------------------------------------------------------------- /.github/dco.yml: -------------------------------------------------------------------------------- 1 | # This enables DCO bot - https://github.com/probot/dco for more details. 2 | # Exclude org members from DCO sign-off on commits 3 | require: 4 | members: false 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | pull-request-branch-name: 8 | separator: "-" 9 | - package-ecosystem: "gomod" 10 | directory: "/" 11 | open-pull-requests-limit: 10 12 | schedule: 13 | interval: "daily" 14 | pull-request-branch-name: 15 | separator: "-" 16 | # Custom settings 17 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## PR summary 2 | 3 | 4 | 5 | Fixes: 6 | 7 | **Note: An existing issue is [required](https://github.com/IBM/cloudant-go-sdk/blob/main/CONTRIBUTING.md#PRs) before opening a PR.** 8 | 9 | ## PR Checklist 10 | 11 | Please make sure that your PR fulfills the following requirements: 12 | 13 | - [ ] The commit message follows the 14 | [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines). 15 | - [ ] Tests for the changes have been added (for bug fixes / features) 16 | - [ ] Docs have been added / updated (for bug fixes / features) 17 | 18 | ## PR Type 19 | 20 | - [ ] Bugfix 21 | - [ ] Feature 22 | - [ ] Code style update (formatting, local variables) 23 | - [ ] Refactoring (no functional changes, no api changes) 24 | - [ ] New tests 25 | - [ ] Build/CI related changes 26 | - [ ] Documentation content changes 27 | - [ ] Other (please describe) 28 | 29 | ## What is the current behavior? 30 | 31 | 32 | ## What is the new behavior? 33 | 34 | 35 | ## Does this PR introduce a breaking change? 36 | 37 | - [ ] Yes 38 | - [ ] No 39 | 40 | 42 | 43 | ## Other information 44 | 45 | 47 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | on: 3 | push: 4 | branches: ['main'] 5 | pull_request: 6 | branches: ['main'] 7 | schedule: 8 | - cron: '54 3 * * 2' 9 | permissions: {} 10 | jobs: 11 | analyze: 12 | name: Analyze 13 | runs-on: ubuntu-latest 14 | permissions: 15 | security-events: write 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | language: ['go'] 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 23 | - name: Initialize CodeQL 24 | uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 25 | with: 26 | languages: ${{ matrix.language }} 27 | - name: Autobuild 28 | uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 29 | - name: Perform CodeQL Analysis 30 | uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 31 | with: 32 | category: "/language:${{matrix.language}}" 33 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | on: 3 | pull_request: 4 | branches: ['main'] 5 | permissions: {} 6 | env: 7 | GOTOOLCHAIN: local 8 | jobs: 9 | docs: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | with: 15 | persist-credentials: false 16 | - name: Install Go 1.23 17 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 18 | with: 19 | go-version: '1.23' 20 | check-latest: true 21 | cache: true 22 | - name: Build docs 23 | run: | 24 | for pkg in auth common features cloudantv1 25 | do 26 | go doc -all -u $pkg 27 | done 28 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: 3 | push: 4 | branches: ['main'] 5 | pull_request: 6 | branches-ignore: ['gh-pages'] 7 | permissions: {} 8 | env: 9 | GOTOOLCHAIN: local 10 | WIREMOCK_URL: http://127.0.0.1:8080 11 | WIREMOCK_PORT: 8080 12 | jobs: 13 | test: 14 | strategy: 15 | matrix: 16 | go: ['1.23', '1.24'] 17 | runs-on: ubuntu-latest 18 | services: 19 | wiremock: 20 | image: wiremock/wiremock 21 | options: --name wiremock 22 | ports: 23 | - 8080:8080 24 | steps: 25 | - name: Checkout code 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | with: 28 | persist-credentials: false 29 | - name: Install Go ${{ matrix.go }} 30 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 31 | with: 32 | go-version: ${{ matrix.go }} 33 | check-latest: true 34 | cache: true 35 | - name: Setup Wiremock 36 | shell: bash 37 | run: ${GITHUB_WORKSPACE}/scripts/setup_wiremock.sh 38 | - name: Run tests 39 | run: go test ./... -coverprofile=coverage.txt -covermode=count 40 | - name: Run lint 41 | uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | 4 | # ignore vendor/ 5 | vendor/ 6 | 7 | # SDK generator 8 | .openapi-generator-ignore 9 | .openapi-generator/VERSION 10 | /.project 11 | 12 | # credentials files 13 | *.env 14 | 15 | package-lock.json 16 | junitreports 17 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | default: none 4 | enable: 5 | - errcheck 6 | - goheader 7 | - govet 8 | - ineffassign 9 | - staticcheck 10 | - unused 11 | settings: 12 | goheader: 13 | values: 14 | regexp: 15 | COPYRIGHT: (© Copyright IBM Corporation 20\d{2}(?:, 20\d{2})?\. All Rights Reserved\.|\(C\) Copyright IBM Corp\. 20\d{2}\.) 16 | template-path: config/header-template.txt 17 | exclusions: 18 | generated: lax 19 | presets: 20 | - comments 21 | - common-false-positives 22 | - legacy 23 | - std-error-handling 24 | rules: 25 | - linters: 26 | - errcheck 27 | - govet 28 | - ineffassign 29 | - staticcheck 30 | - unused 31 | path: cloudantv1/cloudant_v1\.go 32 | - linters: 33 | - errcheck 34 | - govet 35 | - ineffassign 36 | - staticcheck 37 | - unused 38 | path: cloudantv1/cloudant_v1_suite_test\.go 39 | - linters: 40 | - errcheck 41 | - govet 42 | - ineffassign 43 | - staticcheck 44 | - unused 45 | path: cloudantv1/cloudant_v1_test\.go 46 | paths: 47 | - third_party$ 48 | - builtin$ 49 | - examples$ 50 | formatters: 51 | enable: 52 | - goimports 53 | exclusions: 54 | generated: lax 55 | paths: 56 | - third_party$ 57 | - builtin$ 58 | - examples$ 59 | - cloudantv1/cloudant_v1\.go 60 | - cloudantv1/cloudant_v1_suite_test\.go 61 | - cloudantv1/cloudant_v1_test\.go 62 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "plugins": [ 4 | "@semantic-release/commit-analyzer", 5 | "@semantic-release/release-notes-generator", 6 | "@semantic-release/changelog", 7 | [ 8 | "@semantic-release/exec", 9 | { 10 | "prepareCmd": "bump2version --allow-dirty --current-version ${lastRelease.version} --new-version ${nextRelease.version} patch" 11 | } 12 | ], 13 | [ 14 | "@semantic-release/git", 15 | { 16 | "message": "chore(release): ${nextRelease.version} release notes [skip ci]\n\n${nextRelease.notes}" 17 | } 18 | ], 19 | "@semantic-release/github" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /.secrets.baseline: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": { 3 | "files": "stubs/.+\\.json|go.sum|^.secrets.baseline$", 4 | "lines": null 5 | }, 6 | "generated_at": "2024-03-21T17:33:46Z", 7 | "plugins_used": [ 8 | { 9 | "name": "AWSKeyDetector" 10 | }, 11 | { 12 | "name": "ArtifactoryDetector" 13 | }, 14 | { 15 | "name": "AzureStorageKeyDetector" 16 | }, 17 | { 18 | "base64_limit": 4.5, 19 | "name": "Base64HighEntropyString" 20 | }, 21 | { 22 | "name": "BasicAuthDetector" 23 | }, 24 | { 25 | "name": "BoxDetector" 26 | }, 27 | { 28 | "name": "CloudantDetector" 29 | }, 30 | { 31 | "ghe_instance": "github.ibm.com", 32 | "name": "GheDetector" 33 | }, 34 | { 35 | "name": "GitHubTokenDetector" 36 | }, 37 | { 38 | "hex_limit": 3, 39 | "name": "HexHighEntropyString" 40 | }, 41 | { 42 | "name": "IbmCloudIamDetector" 43 | }, 44 | { 45 | "name": "IbmCosHmacDetector" 46 | }, 47 | { 48 | "name": "JwtTokenDetector" 49 | }, 50 | { 51 | "keyword_exclude": null, 52 | "name": "KeywordDetector" 53 | }, 54 | { 55 | "name": "MailchimpDetector" 56 | }, 57 | { 58 | "name": "NpmDetector" 59 | }, 60 | { 61 | "name": "PrivateKeyDetector" 62 | }, 63 | { 64 | "name": "SlackDetector" 65 | }, 66 | { 67 | "name": "SoftlayerDetector" 68 | }, 69 | { 70 | "name": "SquareOAuthDetector" 71 | }, 72 | { 73 | "name": "StripeDetector" 74 | }, 75 | { 76 | "name": "TwilioKeyDetector" 77 | } 78 | ], 79 | "results": { 80 | "Jenkinsfile": [ 81 | { 82 | "hashed_secret": "dd7c0356e7bfc571546237209d7fa15319e25cfa", 83 | "is_secret": false, 84 | "is_verified": false, 85 | "line_number": 33, 86 | "type": "Secret Keyword", 87 | "verified_result": null 88 | } 89 | ], 90 | "KNOWN_ISSUES.md": [ 91 | { 92 | "hashed_secret": "0bd9a2b35d06a63d69477ceae7c2d77d3a7e1d75", 93 | "is_secret": false, 94 | "is_verified": false, 95 | "line_number": 200, 96 | "type": "Secret Keyword", 97 | "verified_result": null 98 | }, 99 | { 100 | "hashed_secret": "e0957106541ec9a867ffb5043634a4fb1e1e3aa6", 101 | "is_secret": false, 102 | "is_verified": false, 103 | "line_number": 209, 104 | "type": "Secret Keyword", 105 | "verified_result": null 106 | }, 107 | { 108 | "hashed_secret": "5e158de82a38be416dfed3bef65bfe91c2dc1452", 109 | "is_secret": false, 110 | "is_verified": false, 111 | "line_number": 218, 112 | "type": "Basic Auth Credentials", 113 | "verified_result": null 114 | }, 115 | { 116 | "hashed_secret": "949337ce31eda30d48b66d1990863ad68d4ffea9", 117 | "is_secret": false, 118 | "is_verified": false, 119 | "line_number": 219, 120 | "type": "Basic Auth Credentials", 121 | "verified_result": null 122 | } 123 | ], 124 | "README.md": [ 125 | { 126 | "hashed_secret": "32e8612d8ca77c7ea8374aa7918db8e5df9252ed", 127 | "is_secret": false, 128 | "is_verified": false, 129 | "line_number": 235, 130 | "type": "Secret Keyword", 131 | "verified_result": null 132 | } 133 | ], 134 | "auth/couchdb_session_authenticator_test.go": [ 135 | { 136 | "hashed_secret": "12dea96fec20593566ab75692c9949596833adc9", 137 | "is_secret": false, 138 | "is_verified": false, 139 | "line_number": 43, 140 | "type": "Secret Keyword", 141 | "verified_result": null 142 | }, 143 | { 144 | "hashed_secret": "39eecf6dda11fe10e41163ecf9f25decd0f5d63e", 145 | "is_secret": false, 146 | "is_verified": false, 147 | "line_number": 75, 148 | "type": "Secret Keyword", 149 | "verified_result": null 150 | } 151 | ], 152 | "base/testdata/my-credentials.env": [ 153 | { 154 | "hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750", 155 | "is_secret": false, 156 | "is_verified": false, 157 | "line_number": 22, 158 | "type": "Secret Keyword", 159 | "verified_result": null 160 | }, 161 | { 162 | "hashed_secret": "edbd5e119f94badb9f99a67ac6ff4c7a5204ad61", 163 | "is_secret": false, 164 | "is_verified": false, 165 | "line_number": 28, 166 | "type": "Secret Keyword", 167 | "verified_result": null 168 | } 169 | ], 170 | "cloudantv1/cloudant_v1.go": [ 171 | { 172 | "hashed_secret": "0f82cb79406158a202e5e4dafef566c09c620fa9", 173 | "is_secret": false, 174 | "is_verified": false, 175 | "line_number": 6449, 176 | "type": "Secret Keyword", 177 | "verified_result": null 178 | }, 179 | { 180 | "hashed_secret": "9010fd9ef3ce50b1d897190013c7fa86ea3f8f6f", 181 | "is_secret": false, 182 | "is_verified": false, 183 | "line_number": 16130, 184 | "type": "Secret Keyword", 185 | "verified_result": null 186 | }, 187 | { 188 | "hashed_secret": "6452e7c5a42f97b00af1a210afc7d4de315e57ec", 189 | "is_secret": false, 190 | "is_verified": false, 191 | "line_number": 16153, 192 | "type": "Secret Keyword", 193 | "verified_result": null 194 | }, 195 | { 196 | "hashed_secret": "fe7042cb74a5576f32a19f0f44a2c6e304936b11", 197 | "is_secret": false, 198 | "is_verified": false, 199 | "line_number": 16741, 200 | "type": "Secret Keyword", 201 | "verified_result": null 202 | } 203 | ], 204 | "cloudantv1/cloudant_v1_integration_test.go": [ 205 | { 206 | "hashed_secret": "41fbfd5105c450cf79e406dee4cc74cd55817fc2", 207 | "is_secret": false, 208 | "is_verified": false, 209 | "line_number": 1928, 210 | "type": "Secret Keyword", 211 | "verified_result": null 212 | } 213 | ], 214 | "cloudantv1/cloudant_v1_test.go": [ 215 | { 216 | "hashed_secret": "1f5e25be9b575e9f5d39c82dfd1d9f4d73f1975c", 217 | "is_secret": false, 218 | "is_verified": false, 219 | "line_number": 59, 220 | "type": "Secret Keyword", 221 | "verified_result": null 222 | }, 223 | { 224 | "hashed_secret": "949bbd3bf220ef8a77cd533ca09812200b217641", 225 | "is_secret": false, 226 | "is_verified": false, 227 | "line_number": 18167, 228 | "type": "Secret Keyword", 229 | "verified_result": null 230 | }, 231 | { 232 | "hashed_secret": "d461e16a38fb0912ef88e20f39864efa30da268d", 233 | "is_secret": false, 234 | "is_verified": false, 235 | "line_number": 27387, 236 | "type": "Secret Keyword", 237 | "verified_result": null 238 | }, 239 | { 240 | "hashed_secret": "b8473b86d4c2072ca9b08bd28e373e8253e865c4", 241 | "is_secret": false, 242 | "is_verified": false, 243 | "line_number": 27547, 244 | "type": "Secret Keyword", 245 | "verified_result": null 246 | }, 247 | { 248 | "hashed_secret": "b5366a2d2ac98dae978423083f8b09e5cddc705d", 249 | "is_secret": false, 250 | "is_verified": false, 251 | "line_number": 27931, 252 | "type": "Secret Keyword", 253 | "verified_result": null 254 | } 255 | ], 256 | "examples/README.md": [ 257 | { 258 | "hashed_secret": "ee5845e8eca8bbb844825afebf13a3726e0605d9", 259 | "is_secret": false, 260 | "is_verified": false, 261 | "line_number": 388, 262 | "type": "Secret Keyword", 263 | "verified_result": null 264 | } 265 | ], 266 | "examples/snippets/putReplicationDocument/example_request.go": [ 267 | { 268 | "hashed_secret": "ee5845e8eca8bbb844825afebf13a3726e0605d9", 269 | "is_secret": false, 270 | "is_verified": false, 271 | "line_number": 24, 272 | "type": "Secret Keyword", 273 | "verified_result": null 274 | } 275 | ] 276 | }, 277 | "version": "0.13.1+ibm.62.dss", 278 | "word_list": { 279 | "file": null, 280 | "hash": null 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "settingsInheritedFrom": "whitesource-config/whitesource-config@master", 3 | "issueSettings": { 4 | "issueRepoName": "sdks" 5 | }, 6 | "scanSettings": { 7 | "javaVersion": "17", 8 | "python.requirementsFileIncludes": "pyproject.toml,requirements-dev.txt,requirements-docs.txt" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at [IBM Cloud Support](https://www.ibm.com/cloud/support). 59 | All complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Questions 2 | If you are having problems using the APIs or have a question about IBM Cloud services, 3 | please ask a question at 4 | [Stack Overflow](http://stackoverflow.com/questions/ask?tags=ibm-cloud). 5 | 6 | # Issues 7 | If you encounter an issue with the project, you are welcome to submit a 8 | [bug report](https://github.com/IBM/cloudant-go-sdk/issues). 9 | Before that, please search for similar issues. It's possible that someone has already reported the problem. 10 | 11 | # PRs 12 | We ask that an **issue is always opened prior to a PR** to give us the 13 | opportunity to discuss the best place for the change before investing 14 | your effort on a patch that we may not be able to accept. 15 | 16 | The code in the repository is partly generated from the Cloudant OpenAPI 17 | specification. This means PRs to code, tests and sometimes even markdown 18 | are often inappropriate and we may need to make changes to the specification 19 | instead. Please, first [look at the list of files](.github/CODEOWNERS) that 20 | _should not_ be modified. 21 | 22 | # General Information 23 | For general guidance on contributing to this project, please see the 24 | [general guidance for contributing](https://github.com/IBM/ibm-cloud-sdk-common/blob/main/CONTRIBUTING_go.md). 25 | -------------------------------------------------------------------------------- /KNOWN_ISSUES.md: -------------------------------------------------------------------------------- 1 | # Limitations, Restrictions, and Known Issues 2 | 3 | ## All Cloudant SDKs 4 | 5 | ### Path elements containing the `+` character 6 | 7 | Path elements containing the `+` character in the SDKs are not interoperable with: 8 | * Cloudant 9 | * Apache CouchDB versions older than 3.2.0 10 | * Apache CouchDB versions 3.2.0 or newer with the setting `decode_plus_to_space = true` 11 | 12 | This is because standard URL encoding libraries following the [RFC3986 URI specification](https://tools.ietf.org/html/rfc3986#section-3.3) do not encode the `+` character in path elements. 13 | * It is possible to workaround for document names with a `+` in the ID (e.g. `docidwith+char`) by using: 14 | * For reading: use the `post` all docs operation and the `key` or `keys` parameter with a value of the document ID including the `+`. 15 | * For writing: use the `post` document operation or `post` bulk docs operation with the value of the document ID including the `+`. 16 | * There is no pre-encoding workaround because the result is a double encoding e.g. using `%2b` in the path element ends up being double encoded as `%252b`. 17 | 18 | ### Views 19 | 20 | #### Objects as keys 21 | 22 | Using JSON objects as keys (e.g. `start_key`, `end_key`, `key`, `keys`) 23 | can cause inconsistent results because the ordering of the members of the JSON 24 | object after serialization is not guaranteed. 25 | 26 | ### Documents 27 | 28 | #### Attachments 29 | 30 | The `atts_since` parameter is not supported when retrieving a document. 31 | The workaround is to call `POST /{db}/_bulk_get` using the `atts_since` field under the `docs` request body. See the [alternative example request for `atts_since` using the `/_bulk_get` endpoint](https://cloud.ibm.com/apidocs/cloudant#postbulkget) in our API Docs. 32 | Example JSON request body: 33 | ```json 34 | { 35 | "docs": [{"id": "order00058", "atts_since": "1-99b02e08da151943c2dcb40090160bb8"}] 36 | } 37 | ``` 38 | 39 | #### Open revisions 40 | 41 | The `open_revs` parameter is not supported when retrieving a document. 42 | If you want to retrieve documents with all leaf revisions (`open_revs=all`), the workaround is to call `POST /{db}/_bulk_get` using the `id` field within the `docs` array request body. 43 | See the [alternative example request for `open_revs=all` using the `/_bulk_get` endpoint](https://cloud.ibm.com/apidocs/cloudant#postbulkget) in our API Docs. 44 | Example JSON request body: 45 | ```json 46 | { 47 | "docs": [{"id": "order00067"}] 48 | } 49 | ``` 50 | 51 | If you want to retrieve documents of specified leaf revisions (e.g. `open_revs=["3-917fa2381192822767f010b95b45325b", "4-a5be949eeb7296747cc271766e9a498b"]`), the workaround is to call `POST /{db}/_bulk_get` using the same `id` value for each unique `rev` value within of the `docs` array request body. 52 | See the [default example request using the `/_bulk_get` endpoint](https://cloud.ibm.com/apidocs/cloudant#postbulkget) in our API Docs. 53 | Example JSON request body: 54 | ```json 55 | { 56 | "docs": [ 57 | { 58 | "id": "order00067", 59 | "rev": "3-917fa2381192822767f010b95b45325b" 60 | }, 61 | { 62 | "id": "order00067", 63 | "rev": "4-a5be949eeb7296747cc271766e9a498b" 64 | } 65 | ] 66 | } 67 | ``` 68 | 69 | ### Compression 70 | 71 | * Manually setting an `Accept-Encoding` header on requests will disable the transparent gzip decompression of response bodies from the server. 72 | * Manually setting a `Content-Encoding` header on requests will disable the transparent gzip compression of request bodies to the server. 73 | 74 | ### Changes feed 75 | 76 | #### Filter functions 77 | 78 | The SDK does not support passing user-defined query or body parameters in `_changes` requests for dynamic filter functions in design documents. 79 | The workaround and recommended option is to use a `selector` type filter. 80 | For example, if you are using a `_changes` request like `/{db}/_changes?filter=myDdoc/byName&name=Jane` with a filter function like: 81 | ```javascript 82 | function(doc, req) { 83 | if (doc.name !== req.query.name) { 84 | return false; 85 | } 86 | return true; 87 | } 88 | ``` 89 | It can be replaced with a request using a selector filter: 90 | ```go 91 | postChangesOptions := service.NewPostChangesOptions("example"). 92 | SetFilter("_selector"). 93 | SetSelector(map[string]interface{}{"name": "Jane"}) 94 | 95 | changesResult, response, err := service.PostChanges(postChangesOptions) 96 | if err != nil { 97 | panic(err) 98 | } 99 | ``` 100 | 101 | 102 | ## Cloudant SDK for Go 103 | 104 | ### Search 105 | #### Analyzer definitions should be in object format 106 | 107 | * In order to be able to deserialize a design document with a search 108 | index analyzer into the model object the analyzer must be stored in the design 109 | document described in object format, not a string format e.g. 110 | ```json 111 | { 112 | "analyzer": { 113 | "name": "keyword" 114 | } 115 | } 116 | ``` 117 | not 118 | ```json 119 | { 120 | "analyzer": "keyword" 121 | } 122 | ``` 123 | Note that analyzers created using the SDK's struct models use the object format. As such the issue will only manifest 124 | when trying to read a design document created from another source with this error: 125 | ``` 126 | json: cannot unmarshal string into Go value of type map[string]json.RawMessage 127 | ``` 128 | 129 | #### Facet counting deserialization errors in no match cases 130 | 131 | In Apache CouchDB versions `3.3.2` or older and Cloudant versions `8435` and older 132 | when obtaining a `SearchResult` with `counts` if there are no matches a deserialization error is encountered. 133 | 134 | The workaround is to use [Raw IO](/#raw-io) functions to custom deserialize the response. 135 | 136 | ### Request bodies containing the `headers` parameter 137 | 138 | The `Headers` map is always reserved for the API request headers. 139 | In order to avoid collision between the request headers and the `headers` parameter 140 | that is contained by the request body, use the `HeadersVar` as 141 | the request body `headers` parameter. 142 | 143 | E.g. to set the `headers` parameter of your replication 144 | target database, use the following approach: 145 | 146 | ```go 147 | ... 148 | target, _ := cloudant.NewReplicationDatabase( 149 | "" + "/" + "animaldb-target", 150 | ) 151 | 152 | target.HeadersVar = make(map[string]string) 153 | target.HeadersVar["Authorization"] = "Basic " 154 | ... 155 | ``` 156 | The example above represents this JSON body: 157 | ```json 158 | { 159 | ... 160 | "target": { 161 | "headers": { 162 | "Authorization": "Basic " 163 | }, 164 | "url": "/animaldb-target" 165 | }, 166 | ... 167 | } 168 | ``` 169 | 170 | ### Disabling request body compression 171 | 172 | Some issues with older server versions can be worked around by disabling 173 | compression of request bodies. This is an example of how to do that. 174 | 175 | ```go 176 | import ( 177 | "github.com/ibm/cloudant-go-sdk/cloudantv1" 178 | ) 179 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 180 | &cloudantv1.CloudantV1Options{ 181 | ServiceName: "{your-service-name}", 182 | }, 183 | ) 184 | client.SetEnableGzipCompression(false) 185 | ... 186 | ``` 187 | 188 | #### Request body write errors on 4xx responses from Apache CouchDB 189 | 190 | This problem has been observed only when using request body compression (enabled by default), HTTP/1.1 protocol, and an Apache CouchDB server. It is not known to impact IBM Cloudant. 191 | 192 | When a request is made that is rejected by the server (for example a `409 conflict` repsonse) then in very rare cases the client may return an error writing the request body (for example `write: connection reset by peer` or `write: broken pipe`) instead of the `4xx` error returned by the server. This occurs because the client is still writing the request body after the CouchDB server has already responded with an error and terminated the connection. In nearly all cases the server error is returned correctly. However, if you experience a scenario where this issue occurs a workaround is to disable request body compression as outlined in the example above. 193 | 194 | 195 | ### Replication Documents 196 | 197 | * In order to be able to deserialize a replication document into the model 198 | object the source and target databases must be stored in an object format, 199 | not a string format e.g. 200 | ```json 201 | { 202 | "source": { 203 | "url": "https:///animaldb", 204 | "auth" : { 205 | "basic": { 206 | "username": "", 207 | "password": "" 208 | } 209 | } 210 | }, 211 | "target": { 212 | "url": "https:///animaldb-target", 213 | "auth" : { 214 | "basic": { 215 | "username": "", 216 | "password": "" 217 | } 218 | } 219 | } 220 | } 221 | ``` 222 | not 223 | ```json 224 | { 225 | "source": "https://:@", 226 | "target": "https://:@" 227 | } 228 | ``` 229 | Note that replication documents created using the SDK's struct models use the object format. As such the issue will only manifest 230 | when trying to read a replication document created from another source with this error: 231 | ```sh 232 | json: cannot unmarshal string into Go value of type map[string]json.RawMessage 233 | ``` 234 | If you need to read a replication document that uses string format source or target URLs the workaround is to use the `GetDocumentAsStream` [Raw IO](/#raw-io) function with the `_replicator` database name and your replication document id to custom deserialize the response. 235 | 236 | ### Queries 237 | 238 | #### Explain response 239 | 240 | With Apache CouchDB versions `3.3.2` or older and Cloudant versions `8442` and older 241 | deserialization of the `_explain` response fails when the request does not 242 | list any `fields` to project and hence the response includes `"fields": "all_fields"`. 243 | 244 | If it is not possible to use a newer server version the workaround is to use 245 | [Raw IO](/#raw-io) functions to custom deserialize the response. 246 | 247 | ### Design documents 248 | 249 | #### Query language design documents 250 | 251 | The type of the `map` function for `views` differs between design documents with `"language":"javascript"` (`map` function is a string) and `"language":"query"` (`map` function is an object). 252 | 253 | The SDK model for a design document expects a `javascript` design document and the [`GetDesignDocument` operation](https://cloud.ibm.com/apidocs/cloudant?code=go#getdesigndocument) fails for a `query` design document with an error such as `error unmarshalling cloudantv1.DesignDocument: error unmarshalling property 'views' as map[string]cloudantv1.DesignDocumentViewsMapReduce: error unmarshalling property 'map': json: cannot unmarshal object into Go value of type string`. 254 | 255 | In general manage `query` design documents using the `_index` endpoint operations: [`PostIndex`](https://cloud.ibm.com/apidocs/cloudant?code=go#postindex), [`DeleteIndex`](https://cloud.ibm.com/apidocs/cloudant?code=go#deleteindex), and [`GetIndexesInformation`](https://cloud.ibm.com/apidocs/cloudant?code=go#getindexesinformation). However, if you must retrieve the content of a `query` design document workaround the error by using the [`PostDesignDocs` operation](https://cloud.ibm.com/apidocs/cloudant?code=go#postdesigndocs) with the `IncludeDocs` parameter and the `Key` parameter to limit the response to a single specific design document. If a completely raw response is preferred then instead use the [`PostAllDocsAsStream operation`](https://cloud.ibm.com/apidocs/cloudant?code=go#postalldocs). 256 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | latest | :white_check_mark: | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | If you believe you have found a vulnerability please report it responsibly. IBM has documented the process for reporting vulnerabilities at https://www.ibm.com/trust/security-psirt. 12 | 13 | ## Vulnerabilities in dependencies 14 | 15 | The SDK is regularly scanned for known CVEs in dependencies and updates to versions with remediations are applied and released as soon as possible. 16 | Reporting known CVEs in dependencies in this repository is not necessary and will not lead to a faster resolution. 17 | -------------------------------------------------------------------------------- /auth/auth_suite_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package auth 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestCloudantV1(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Auth Suite") 29 | } 30 | -------------------------------------------------------------------------------- /auth/couchdb_session_authenticator.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2024. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package auth 18 | 19 | import ( 20 | "bytes" 21 | "context" 22 | "fmt" 23 | "net/http" 24 | "sync" 25 | 26 | "github.com/IBM/cloudant-go-sdk/common" 27 | "github.com/IBM/go-sdk-core/v5/core" 28 | ) 29 | 30 | const ( 31 | AUTHTYPE_COUCHDB_SESSION = "COUCHDB_SESSION" 32 | ) 33 | 34 | // CouchDbSessionAuthenticator uses username and password to obtain 35 | // CouchDB authentication cookie, and adds the cookie to requests. 36 | type CouchDbSessionAuthenticator struct { 37 | // [Required] The username and password used to access CouchDB session end-point 38 | Username, Password string 39 | 40 | // HTTP client used to to obtain CouchDB authentication cookie. 41 | client *http.Client 42 | 43 | // CouchDB URL inherited from the service request. 44 | URL string 45 | 46 | // Client's headers inherited from the service request. 47 | header http.Header 48 | 49 | // Context inherited from from the service request. 50 | ctx context.Context 51 | 52 | // A flag that indicates whether verification of the server's SSL certificate should be disabled 53 | DisableSSLVerification bool 54 | 55 | // A session instance that stores and manages the authentication cookie. 56 | session *session 57 | 58 | // A buffer chanel to hold on refreshed session. 59 | refresh chan *session 60 | 61 | // Authenticator mutex used in getCookie() to make it thread-safe to use from concurrent goroutines. 62 | mu sync.Mutex 63 | } 64 | 65 | // NewCouchDbSessionAuthenticator constructs a new NewCouchDbSessionAuthenticator instance. 66 | func NewCouchDbSessionAuthenticator(username, password string) (*CouchDbSessionAuthenticator, error) { 67 | authenticator := &CouchDbSessionAuthenticator{ 68 | Username: username, 69 | Password: password, 70 | refresh: make(chan *session, 1), 71 | } 72 | if err := authenticator.Validate(); err != nil { 73 | return nil, err 74 | } 75 | client := core.DefaultHTTPClient() 76 | authenticator.SetClient(client) 77 | return authenticator, nil 78 | } 79 | 80 | // NewCouchDbSessionAuthenticatorFromMap constructs a new NewCouchDbSessionAuthenticator instance from a map. 81 | func NewCouchDbSessionAuthenticatorFromMap(props map[string]string) (*CouchDbSessionAuthenticator, error) { 82 | if props == nil { 83 | return nil, core.SDKErrorf(nil, core.ERRORMSG_PROPS_MAP_NIL, "missing-props", common.GetComponentInfo()) 84 | } 85 | username := props[core.PROPNAME_USERNAME] 86 | password := props[core.PROPNAME_PASSWORD] 87 | return NewCouchDbSessionAuthenticator(username, password) 88 | } 89 | 90 | // AuthenticationType returns the authentication type for this authenticator. 91 | func (a *CouchDbSessionAuthenticator) AuthenticationType() string { 92 | return AUTHTYPE_COUCHDB_SESSION 93 | } 94 | 95 | // Validate the authenticator's configuration. 96 | // Ensures the service url, username and password are valid and not nil. 97 | func (a *CouchDbSessionAuthenticator) Validate() error { 98 | if a.Username == "" { 99 | return core.SDKErrorf(nil, fmt.Sprintf(core.ERRORMSG_PROP_MISSING, "Username"), "no-user", common.GetComponentInfo()) 100 | } 101 | 102 | if a.Password == "" { 103 | return core.SDKErrorf(nil, fmt.Sprintf(core.ERRORMSG_PROP_MISSING, "Password"), "no-pass", common.GetComponentInfo()) 104 | } 105 | 106 | if core.HasBadFirstOrLastChar(a.Username) { 107 | return core.SDKErrorf(nil, fmt.Sprintf(core.ERRORMSG_PROP_INVALID, "Username"), "bad-user", common.GetComponentInfo()) 108 | } 109 | 110 | if core.HasBadFirstOrLastChar(a.Password) { 111 | return core.SDKErrorf(nil, fmt.Sprintf(core.ERRORMSG_PROP_INVALID, "Password"), "bad-pass", common.GetComponentInfo()) 112 | } 113 | 114 | return nil 115 | } 116 | 117 | // Authenticate adds session authentication cookie to a request. 118 | func (a *CouchDbSessionAuthenticator) Authenticate(request *http.Request) error { 119 | a.URL = request.URL.Scheme + "://" + request.URL.Host 120 | a.header = request.Header 121 | a.ctx = request.Context() 122 | 123 | cookie, err := a.refreshCookie() 124 | if err != nil { 125 | return err 126 | } 127 | 128 | if a.client.Jar == nil && a.session != nil { 129 | request.AddCookie(cookie) 130 | } 131 | 132 | return err 133 | } 134 | 135 | // SetClient sets the http client for the authenticator. 136 | func (a *CouchDbSessionAuthenticator) SetClient(client *http.Client) { 137 | a.client = client 138 | } 139 | 140 | // refreshCookie checks if an AuthSession cookie needs to be refreshed. 141 | // A new cookie will be fetched and returned from the session end-point 142 | // when needed. 143 | func (a *CouchDbSessionAuthenticator) refreshCookie() (*http.Cookie, error) { 144 | a.mu.Lock() 145 | defer a.mu.Unlock() 146 | 147 | a.flushRefreshChannel() 148 | 149 | if a.session == nil || !a.session.isValid() { 150 | newSession, err := a.requestSession() 151 | if err != nil { 152 | return nil, err 153 | } 154 | a.session = newSession 155 | } else if a.session.needsRefresh() { 156 | // start a background process to refresh the session. 157 | // the refreshed session will be passed to a buffered channel 158 | // and updated in a next request at flushRefreshChannel() call. 159 | go func() { 160 | // we are intentionally not returning errors to the parent process 161 | // to avoid raisng error to a client with still valid session. 162 | session, err := a.requestSession() 163 | if err != nil { 164 | return 165 | } 166 | a.refresh <- session 167 | }() 168 | } 169 | 170 | return a.session.getCookie(), nil 171 | } 172 | 173 | // flushRefreshChannel drains authenticator's refresh channel 174 | // and updates session var with instance from the channel. 175 | // This is none-blocking no-op call when channel's empty. 176 | func (a *CouchDbSessionAuthenticator) flushRefreshChannel() { 177 | select { 178 | case session := <-a.refresh: 179 | a.session = session 180 | default: 181 | } 182 | } 183 | 184 | // requestSession fetches new AuthSession cookie from the server. 185 | func (a *CouchDbSessionAuthenticator) requestSession() (*session, error) { 186 | builder, err := core.NewRequestBuilder(core.POST). 187 | ResolveRequestURL(a.URL, "/_session", nil) 188 | if err != nil { 189 | return nil, err 190 | } 191 | 192 | builder.AddHeader(core.CONTENT_TYPE, "application/x-www-form-urlencoded"). 193 | AddFormData("name", "", "", a.Username). 194 | AddFormData("password", "", "", a.Password). 195 | WithContext(a.ctx) 196 | 197 | // set all the unique headers from original request's client 198 | for key, value := range a.header { 199 | if _, ok := builder.Header[key]; !ok { 200 | builder.Header[key] = value 201 | } 202 | } 203 | 204 | req, err := builder.Build() 205 | if err != nil { 206 | return nil, err 207 | } 208 | 209 | req.SetBasicAuth(a.Username, a.Password) 210 | 211 | resp, err := a.client.Do(req) 212 | if err != nil { 213 | return nil, core.SDKErrorf(err, "", "auth-session-request-fail", common.GetComponentInfo()) 214 | } 215 | 216 | if resp.StatusCode < 200 || resp.StatusCode >= 300 { 217 | buff := new(bytes.Buffer) 218 | _, _ = buff.ReadFrom(resp.Body) 219 | 220 | detailedResponse := &core.DetailedResponse{ 221 | StatusCode: resp.StatusCode, 222 | Headers: resp.Header, 223 | RawResult: buff.Bytes(), 224 | } 225 | err := fmt.Errorf("%s", buff) 226 | 227 | cInfo := common.GetComponentInfo() 228 | component := core.NewProblemComponent(cInfo.Name, cInfo.Version) 229 | 230 | discriminator := "auth-session-failed" 231 | 232 | problem := &core.HTTPProblem{ 233 | IBMProblem: core.IBMErrorf(err, component, "", discriminator), 234 | Response: detailedResponse, 235 | } 236 | 237 | summary := fmt.Sprintf(core.ERRORMSG_AUTHENTICATE_ERROR, err.Error()) 238 | 239 | return nil, core.SDKErrorf(problem, summary, discriminator, cInfo) 240 | } 241 | 242 | var session *session 243 | for _, cookie := range resp.Cookies() { 244 | if cookie.Name == "AuthSession" { 245 | session, err = newSession(cookie) 246 | if err != nil { 247 | return nil, err 248 | } 249 | break 250 | } 251 | } 252 | 253 | if session == nil { 254 | err := fmt.Errorf("missing AuthSession cookie in the response") 255 | return nil, core.SDKErrorf(err, "", "missing-auth-cookie", common.GetComponentInfo()) 256 | } 257 | 258 | return session, nil 259 | } 260 | -------------------------------------------------------------------------------- /auth/session.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package auth 18 | 19 | import ( 20 | "net/http" 21 | "sync" 22 | "time" 23 | ) 24 | 25 | // endOfTime is the time when session (non-persistent) cookies expire. 26 | var endOfTime = time.Now().AddDate(0, 0, 14) 27 | 28 | // session represent CouchDB AuthSession token and its expiration period. 29 | type session struct { 30 | cookie *http.Cookie 31 | expires time.Time 32 | refreshTime time.Time 33 | refreshMutex sync.Mutex 34 | } 35 | 36 | // newSession returns new session object constructed from AuthSession cookie. 37 | func newSession(c *http.Cookie) (*session, error) { 38 | expires := c.Expires 39 | if expires.IsZero() { 40 | expires = endOfTime 41 | } 42 | 43 | // refreshTime is 20% of period between now and the expiration time 44 | return &session{ 45 | cookie: c, 46 | expires: expires, 47 | refreshTime: expires.Add(-(time.Until(expires) * 20 / 100)), 48 | }, nil 49 | } 50 | 51 | func (s *session) getCookie() *http.Cookie { 52 | return s.cookie 53 | } 54 | 55 | // isValid checks if the auth cookie hasn't expired yet 56 | func (s *session) isValid() bool { 57 | return time.Now().Before(s.expires) 58 | } 59 | 60 | // needsRefresh atomically identifies if the cookie is near of the expiration time 61 | func (s *session) needsRefresh() bool { 62 | now := time.Now() 63 | if now.After(s.refreshTime) { 64 | s.refreshMutex.Lock() 65 | defer s.refreshMutex.Unlock() 66 | 67 | // advance refresh time by one minute to prevent a parallel process 68 | // that might be waiting on mutex right now 69 | // from starting the second refresh process 70 | if now.After(s.refreshTime) { 71 | s.refreshTime = time.Now().Add(time.Minute) 72 | return true 73 | } 74 | return false 75 | } 76 | return false 77 | } 78 | -------------------------------------------------------------------------------- /auth/session_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package auth 18 | 19 | import ( 20 | "encoding/base64" 21 | "fmt" 22 | "net/http" 23 | "time" 24 | 25 | . "github.com/onsi/ginkgo" 26 | . "github.com/onsi/gomega" 27 | ) 28 | 29 | var _ = Describe("Session Unit Tests", func() { 30 | It("Create new Session", func() { 31 | cookie := &http.Cookie{ 32 | Name: "AuthSession", 33 | Value: makeAuthToken(), 34 | Expires: time.Now().Add(24 * time.Hour), 35 | } 36 | 37 | s, err := newSession(cookie) 38 | 39 | Expect(err).To(BeNil()) 40 | Expect(s).ToNot(BeNil()) 41 | Expect(s.getCookie()).To(Equal(cookie)) 42 | Expect(s.expires).To(Equal(cookie.Expires)) 43 | Expect(s.refreshTime).To(BeTemporally("<", s.expires)) 44 | Expect(s.isValid()).To(BeTrue()) 45 | }) 46 | 47 | It("Create new Session for non-persistent cookie", func() { 48 | cookie := &http.Cookie{ 49 | Name: "AuthSession", 50 | Value: makeAuthToken(), 51 | } 52 | 53 | s, err := newSession(cookie) 54 | 55 | Expect(err).To(BeNil()) 56 | Expect(s).ToNot(BeNil()) 57 | Expect(s.getCookie()).To(Equal(cookie)) 58 | Expect(s.expires).ToNot(BeZero()) 59 | Expect(s.refreshTime).To(BeTemporally("<", s.expires)) 60 | Expect(s.isValid()).To(BeTrue()) 61 | }) 62 | 63 | It("Test calculation of refresh time", func() { 64 | cookie := &http.Cookie{ 65 | Name: "AuthSession", 66 | Value: makeAuthToken(), 67 | Expires: time.Now().Add(24 * time.Hour), 68 | } 69 | 70 | s, err := newSession(cookie) 71 | Expect(err).To(BeNil()) 72 | Expect(s).ToNot(BeNil()) 73 | 74 | // 20% of 24h is 4h48m 75 | expected := 4*time.Hour + 48*time.Minute 76 | roundedExpiration := s.expires.Sub(s.refreshTime).Round(time.Minute) 77 | Expect(roundedExpiration).To(Equal(expected)) 78 | }) 79 | 80 | It("Test Session validation", func() { 81 | cookie := &http.Cookie{ 82 | Name: "AuthSession", 83 | Value: makeAuthToken(), 84 | Expires: time.Now().Add(time.Hour), 85 | } 86 | 87 | s, err := newSession(cookie) 88 | Expect(err).To(BeNil()) 89 | Expect(s).ToNot(BeNil()) 90 | Expect(s.isValid()).To(BeTrue()) 91 | 92 | s.expires = time.Now().Add(-time.Minute) 93 | Expect(s.isValid()).ToNot(BeTrue()) 94 | }) 95 | 96 | It("Test needsRefresh function", func() { 97 | cookie := &http.Cookie{ 98 | Name: "AuthSession", 99 | Value: makeAuthToken(), 100 | Expires: time.Now().Add(time.Hour), 101 | } 102 | 103 | s, err := newSession(cookie) 104 | Expect(err).To(BeNil()) 105 | Expect(s).ToNot(BeNil()) 106 | Expect(s.needsRefresh()).ToNot(BeTrue()) 107 | 108 | // Move time into the refresh window 109 | s.refreshTime = time.Now().Add(-10 * time.Minute) 110 | Expect(s.needsRefresh()).To(BeTrue()) 111 | 112 | expected := time.Now().Add(time.Minute).Round(time.Minute) 113 | Expect(s.refreshTime).To(BeTemporally("~", expected, time.Minute)) 114 | }) 115 | }) 116 | 117 | // makeAuthToken is a helper function that generates mockup AuthSession tokens 118 | func makeAuthToken() string { 119 | user := "ea36876f-f058-4b1a-897e-2468f89ba5d5-bluemix" 120 | ts := time.Now().Add(24 * time.Hour).Unix() 121 | token := []byte(fmt.Sprintf("%s:%X:fakefake", user, ts)) 122 | return base64.StdEncoding.EncodeToString(token) 123 | } 124 | -------------------------------------------------------------------------------- /base/base_suite_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2024. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package base_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestCloudantV1(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Base Suite") 29 | } 30 | -------------------------------------------------------------------------------- /base/cloudant_base.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2021, 2024. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package base 18 | 19 | import ( 20 | "encoding/json" 21 | "fmt" 22 | "net/http" 23 | "net/http/cookiejar" 24 | neturl "net/url" 25 | "runtime" 26 | "strconv" 27 | "strings" 28 | "time" 29 | 30 | "github.com/IBM/cloudant-go-sdk/auth" 31 | "github.com/IBM/cloudant-go-sdk/common" 32 | "github.com/IBM/go-sdk-core/v5/core" 33 | "golang.org/x/net/publicsuffix" 34 | ) 35 | 36 | type BaseService struct { 37 | serviceUrlPathSegmentsSize int 38 | *core.BaseService 39 | } 40 | 41 | type validationRule struct { 42 | pathSegmentIndex int 43 | errorParameterName string 44 | operationIds []string 45 | } 46 | 47 | var docIdRule = validationRule{ 48 | pathSegmentIndex: 1, 49 | errorParameterName: "Document ID", 50 | operationIds: []string{ 51 | "DeleteDocument", 52 | "GetDocument", 53 | "GetDocumentAsMixed", 54 | "GetDocumentAsRelated", 55 | "GetDocumentAsStream", 56 | "HeadDocument", 57 | "PutDocument", 58 | "DeleteAttachment", 59 | "GetAttachment", 60 | "HeadAttachment", 61 | "PutAttachment", 62 | }, 63 | } 64 | var attIdRule = validationRule{ 65 | pathSegmentIndex: 2, 66 | errorParameterName: "Attachment name", 67 | operationIds: []string{ 68 | "DeleteAttachment", 69 | "GetAttachment", 70 | "HeadAttachment", 71 | "PutAttachment", 72 | }, 73 | } 74 | 75 | var validationRules = [...]*validationRule{&docIdRule, &attIdRule} 76 | var rulesByOperation = make(map[string][]*validationRule) 77 | 78 | func init() { 79 | for _, rule := range validationRules { 80 | // Build a map of operation name to a list of validations 81 | for _, operationId := range rule.operationIds { 82 | ruleExists := false 83 | rules, ok := rulesByOperation[operationId] 84 | if ok { 85 | // There are already some rules for this operationId 86 | // Check if the current rule already exists 87 | for _, existingRule := range rules { 88 | if existingRule == rule { 89 | ruleExists = true 90 | break 91 | } 92 | } 93 | } 94 | if !ruleExists { 95 | // The rule didn't exist, append it 96 | rulesByOperation[operationId] = append(rules, rule) 97 | } 98 | } 99 | } 100 | } 101 | 102 | func NewBaseService(opts *core.ServiceOptions) (*BaseService, error) { 103 | baseService, err := core.NewBaseService(opts) 104 | if err != nil { 105 | return &BaseService{}, err 106 | } 107 | 108 | // Set a default value for the User-Agent http header. 109 | baseService.SetUserAgent(buildUserAgent()) 110 | 111 | service := &BaseService{0, baseService} 112 | // Set a default HTTP client 113 | client := core.DefaultHTTPClient() 114 | client.Timeout = 6 * time.Minute 115 | service.SetHTTPClient(client) 116 | 117 | return service, nil 118 | } 119 | 120 | func (c *BaseService) Clone() *BaseService { 121 | baseService := c.BaseService.Clone() 122 | return &BaseService{c.serviceUrlPathSegmentsSize, baseService} 123 | } 124 | 125 | func (c *BaseService) Request(req *http.Request, result interface{}) (detailedResponse *core.DetailedResponse, err error) { 126 | // Extract the operation ID from the request headers. 127 | var operationId string 128 | //nolint 129 | header := req.Header["X-IBMCloud-SDK-Analytics"][0] 130 | for _, element := range strings.Split(header, ";") { 131 | if strings.HasPrefix(element, "operation_id") { 132 | operationId = strings.Split(element, "=")[1] 133 | break 134 | } 135 | } 136 | if operationId != "" { 137 | if rulesToApply, ok := rulesByOperation[operationId]; ok { 138 | requestUrlPathSegments := strings.Split(strings.Trim(req.URL.EscapedPath(), "/"), "/") 139 | // In the no-path case the result is a slice with an empty string 140 | // use a nil slice instead in those cases 141 | if len(requestUrlPathSegments) == 1 && requestUrlPathSegments[0] == "" { 142 | requestUrlPathSegments = []string{} 143 | } 144 | // Check each validation rule that applies to the operation. 145 | for _, rule := range rulesToApply { 146 | // Allow for any path segments that might exist in e.g. the URL of a proxy by offseting from the service URL index. 147 | pathSegmentIndex := c.serviceUrlPathSegmentsSize + rule.pathSegmentIndex 148 | if len(requestUrlPathSegments) > pathSegmentIndex { 149 | segmentToValidate := requestUrlPathSegments[pathSegmentIndex] 150 | if strings.HasPrefix(segmentToValidate, "_") { 151 | segmentToValidateMessage, err := neturl.PathUnescape(segmentToValidate) 152 | if err != nil { 153 | // If we couldn't unescape for some reason, just error with the escaped form 154 | segmentToValidateMessage = segmentToValidate 155 | } 156 | err = fmt.Errorf("%v %v starts with the invalid _ character", rule.errorParameterName, segmentToValidateMessage) 157 | return nil, core.SDKErrorf(err, "", "invalid-parameter", common.GetComponentInfo()) 158 | } 159 | } 160 | } 161 | } 162 | } 163 | return c.BaseService.Request(req, result) 164 | } 165 | 166 | func (c *BaseService) SetServiceURL(url string) error { 167 | err := c.BaseService.SetServiceURL(url) 168 | if err != nil { 169 | return err 170 | } 171 | // Set CouchDb Session's auth URL to Base service URL 172 | if c.Options.Authenticator.AuthenticationType() == auth.AUTHTYPE_COUCHDB_SESSION { 173 | a := c.Options.Authenticator.(*auth.CouchDbSessionAuthenticator) 174 | a.URL = c.GetServiceURL() 175 | } 176 | serviceUrl, err := neturl.ParseRequestURI(c.GetServiceURL()) 177 | if err != nil { 178 | return nil 179 | } 180 | serviceUrlPathSegments := strings.Split(strings.Trim(serviceUrl.EscapedPath(), "/"), "/") 181 | serviceUrlPathSegmentsSize := len(serviceUrlPathSegments) 182 | // In the no-path case the result is a slice with an empty string 183 | // set the size to zero in those cases 184 | if serviceUrlPathSegmentsSize == 1 && serviceUrlPathSegments[0] == "" { 185 | c.serviceUrlPathSegmentsSize = 0 186 | } else { 187 | c.serviceUrlPathSegmentsSize = serviceUrlPathSegmentsSize 188 | } 189 | return nil 190 | } 191 | 192 | // SetHTTPClient will set "client" as the http.Client instance to be used 193 | // to invoke individual HTTP requests. 194 | // If automatic retries are currently enabled on "service", then 195 | // "client" will be set as the embedded client instance within 196 | // the retryable client; otherwise "client" will be stored 197 | // directly on "service". 198 | func (c *BaseService) SetHTTPClient(client *http.Client) { 199 | if client.Transport == nil { 200 | client.Transport = http.DefaultTransport 201 | } 202 | 203 | // wrap client's transport into ErrorResponse unless it was already wrapped 204 | if _, ok := client.Transport.(*ErrorResponse); !ok { 205 | client.Transport = NewErrorResponse(client.Transport) 206 | } 207 | 208 | // set cookiejar on if it is missing 209 | if client.Jar == nil { 210 | // we can ignore the error, jar.New it is actually always returns nil 211 | client.Jar, _ = cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) 212 | } 213 | // Set service's HTTP client as CouchDb Session's client to share cookiejar 214 | if c.Options.Authenticator.AuthenticationType() == auth.AUTHTYPE_COUCHDB_SESSION { 215 | a := c.Options.Authenticator.(*auth.CouchDbSessionAuthenticator) 216 | a.SetClient(client) 217 | } 218 | c.BaseService.SetHTTPClient(client) 219 | } 220 | 221 | // GetAuthenticatorFromEnvironment instantiates an Authenticator 222 | // using service properties retrieved from external config sources. 223 | func GetAuthenticatorFromEnvironment(credentialKey string) (core.Authenticator, error) { 224 | props, err := core.GetServiceProperties(credentialKey) 225 | if err != nil { 226 | return nil, err 227 | } 228 | authType, ok := props[core.PROPNAME_AUTH_TYPE] 229 | if !ok { 230 | // this property is not a member of core's constants 231 | authType, ok = props["AUTHTYPE"] 232 | } 233 | 234 | if ok && strings.EqualFold(authType, auth.AUTHTYPE_COUCHDB_SESSION) { 235 | authenticator, err := auth.NewCouchDbSessionAuthenticatorFromMap(props) 236 | if url, ok := props[core.PROPNAME_SVC_URL]; ok && url != "" { 237 | authenticator.URL = url 238 | } 239 | if disableSSLVerification, ok := props[core.PROPNAME_SVC_DISABLE_SSL]; ok && disableSSLVerification != "" { 240 | boolValue, err := strconv.ParseBool(disableSSLVerification) 241 | if err == nil && boolValue { 242 | authenticator.DisableSSLVerification = true 243 | } 244 | } 245 | return authenticator, err 246 | } 247 | 248 | return core.GetAuthenticatorFromEnvironment(credentialKey) 249 | } 250 | 251 | // buildUserAgent builds the user agent string. 252 | func buildUserAgent() string { 253 | return fmt.Sprintf("cloudant-go-sdk/%s (%s)", common.Version, getSystemInfo()) 254 | } 255 | 256 | // getSystemInfo returns the system information. 257 | func getSystemInfo() string { 258 | return fmt.Sprintf("go.version=%s; os.name=%s os.arch=%s lang=go;", 259 | runtime.Version(), 260 | runtime.GOOS, 261 | runtime.GOARCH, 262 | ) 263 | } 264 | 265 | func UnmarshalPrimitiveSpecial(rawInput map[string]json.RawMessage, propertyName string, result *map[string]map[string]int64, containerObjectType string) (err error) { 266 | if containerObjectType != "*cloudantv1.SearchResult" && containerObjectType != "*cloudantv1.SearchResultProperties" { 267 | err = fmt.Errorf("UnmarshalPrimitiveSpecial is called with the wrong result type: '%s', it should be '*cloudantv1.SearchResult' or '*cloudantv1.SearchResultProperties'", containerObjectType) 268 | return 269 | } 270 | if propertyName != "counts" && propertyName != "ranges" { 271 | err = fmt.Errorf("UnmarshalPrimitiveSpecial is called with the wrong propertyName: '%s', it should be 'counts' or 'ranges'", propertyName) 272 | return 273 | } 274 | 275 | // Unmarshal rawInput with interim map[string]map[string]float64 type: 276 | var converted map[string]map[string]float64 277 | err = core.UnmarshalPrimitive(rawInput, propertyName, &converted) 278 | if err != nil { 279 | return 280 | } 281 | // Marshal it back as rawMsg: 282 | rawMsg, err := json.Marshal(converted) 283 | if err != nil { 284 | err = fmt.Errorf("error marshalling converted property '%s': %s", propertyName, err.Error()) 285 | return 286 | } 287 | 288 | // Unmarshal rawMsg with final map[string]map[string]int64 type 289 | // This should not fail if the given number on the map leaf ends with `.0`: 290 | err = json.Unmarshal(rawMsg, &result) 291 | return 292 | } 293 | -------------------------------------------------------------------------------- /base/error_response_transport.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2024. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package base 18 | 19 | import ( 20 | "bytes" 21 | "encoding/json" 22 | "io" 23 | "net/http" 24 | "strings" 25 | ) 26 | 27 | // ErrorResponse is an error augmentation RoundTripper 28 | // that in case of http error response parses the return body 29 | // and converts it to a closer match to the standard error including adding a trace ID 30 | // and appending the CouchDB/Cloudant error reason to the message 31 | type ErrorResponse struct { 32 | next http.RoundTripper 33 | } 34 | 35 | // NewErrorResponse creates a new ErrorResponse middleware 36 | func NewErrorResponse(rt http.RoundTripper) http.RoundTripper { 37 | return &ErrorResponse{next: rt} 38 | } 39 | 40 | // RoundTrip implements RoundTripper interface 41 | func (er *ErrorResponse) RoundTrip(req *http.Request) (resp *http.Response, err error) { 42 | defer func() { 43 | if err == nil && resp.StatusCode >= http.StatusBadRequest { 44 | ct := resp.Header.Get("Content-Type") 45 | if strings.HasPrefix(ct, "application/json") { 46 | err = transformError(resp) 47 | if err != nil { 48 | resp = nil 49 | } 50 | } 51 | } 52 | }() 53 | 54 | return er.next.RoundTrip(req) 55 | } 56 | 57 | // drainBody reads body into memory and returns two identical ReadClosers 58 | // one of which is safe to read 59 | func drainBody(body io.ReadCloser) (orig, save io.ReadCloser, err error) { 60 | if body == nil || body == http.NoBody { 61 | return http.NoBody, http.NoBody, nil 62 | } 63 | var buf bytes.Buffer 64 | if _, err = buf.ReadFrom(body); err != nil { 65 | return nil, body, err 66 | } 67 | if err = body.Close(); err != nil { 68 | return nil, body, err 69 | } 70 | r := bytes.NewReader(buf.Bytes()) 71 | return io.NopCloser(&buf), io.NopCloser(r), nil 72 | } 73 | 74 | // transformError reads the response's body, parses it as json, augments it, 75 | // encodes back and sets as a new response 76 | func transformError(resp *http.Response) error { 77 | var err error 78 | var save io.ReadCloser 79 | savecl := resp.ContentLength 80 | 81 | save, resp.Body, err = drainBody(resp.Body) 82 | if err != nil { 83 | return err 84 | } 85 | 86 | respError := make(map[string]interface{}) 87 | err = json.NewDecoder(resp.Body).Decode(&respError) 88 | if err != nil { 89 | // since resp is not json we just return it as it is 90 | resp.Body = save 91 | return nil 92 | } 93 | 94 | if _, ok := respError["trace"]; ok { 95 | resp.Body = save 96 | return nil 97 | } 98 | 99 | respErrorWasAugmented := false 100 | if _, ok := respError["errors"]; !ok { 101 | err := make(map[string]string) 102 | if m, ok := respError["error"]; ok { 103 | err["code"] = m.(string) 104 | err["message"] = m.(string) 105 | if m, ok := respError["reason"]; ok && m != "" { 106 | err["message"] += ": " + m.(string) 107 | } 108 | respError["errors"] = []map[string]string{err} 109 | respErrorWasAugmented = true 110 | } 111 | } 112 | 113 | trace := resp.Header.Get("X-Request-Id") 114 | if trace == "" { 115 | trace = resp.Header.Get("X-Couch-Request-Id") 116 | } 117 | if _, ok := respError["errors"]; ok && trace != "" { 118 | respError["trace"] = trace 119 | respErrorWasAugmented = true 120 | } 121 | 122 | if respErrorWasAugmented { 123 | var newErrorJson bytes.Buffer 124 | if err := json.NewEncoder(&newErrorJson).Encode(respError); err == nil { 125 | save = io.NopCloser(&newErrorJson) 126 | if resp.Header.Get("Transfer-Encoding") != "chunked" { 127 | savecl = int64(len(newErrorJson.Bytes())) 128 | } 129 | } 130 | } 131 | 132 | resp.Body = save 133 | resp.ContentLength = savecl 134 | 135 | return nil 136 | } 137 | -------------------------------------------------------------------------------- /base/testdata/my-credentials.env: -------------------------------------------------------------------------------- 1 | # Service1 configured with Auth Session 2 | SERVICE1_AUTH_TYPE=COUCHDB_SESSION 3 | SERVICE1_URL=https://my-couch-1 4 | SERVICE1_USERNAME=my-username 5 | SERVICE1_PASSWORD=my-password 6 | 7 | # Service2 configured with Auth Session in lower case 8 | SERVICE2_AUTH_TYPE=couchdb_session 9 | SERVICE2_URL=https://my-couch-2 10 | SERVICE2_DISABLE_SSL=true 11 | SERVICE2_USERNAME=my-username 12 | SERVICE2_PASSWORD=my-password 13 | 14 | # Service3 configured with IAM 15 | SERVICE3_AUTH_TYPE=IAM 16 | SERVICE3_URL=https://my-couch-3 17 | SERVICE3_APIKEY=my-api-key 18 | 19 | # Service4 configured with IAM and auth type alias 20 | SERVICE4_AUTHTYPE=IAM 21 | SERVICE4_URL=https://my-couch-4 22 | SERVICE4_APIKEY=my-api-key 23 | 24 | # Service5 configured with Basic Auth 25 | SERVICE5_AUTH_TYPE=BASIC 26 | SERVICE5_URL=https://my-couch-5 27 | SERVICE5_USERNAME=my-username 28 | SERVICE5_PASSWORD=my-password 29 | -------------------------------------------------------------------------------- /cloudantv1/cloudant_v1_suite_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) Copyright IBM Corp. 2025. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cloudantv1_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestCloudantV1(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "CloudantV1 Suite") 29 | } 30 | -------------------------------------------------------------------------------- /common/common_suite_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestCloudantV1(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Common Suite") 29 | } 30 | -------------------------------------------------------------------------------- /common/headers.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2024. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/IBM/go-sdk-core/v5/core" 23 | ) 24 | 25 | const ( 26 | headerNameSdkAnalytics = "X-IBMCloud-SDK-Analytics" 27 | ) 28 | 29 | // GetSdkHeaders - returns the set of SDK-specific headers to be included in an outgoing request. 30 | // 31 | // This function is invoked by generated service methods (i.e. methods which implement the REST API operations 32 | // defined within the API definition). The purpose of this function is to give the SDK implementor the opportunity 33 | // to provide SDK-specific HTTP headers that will be sent with an outgoing REST API request. 34 | // This function is invoked for each invocation of a generated service method, 35 | // so the set of HTTP headers could be request-specific. 36 | // 37 | // Parameters: 38 | // 39 | // serviceName - the name of the service as defined in the API definition (e.g. "MyService1") 40 | // serviceVersion - the version of the service as defined in the API definition (e.g. "V1") 41 | // operationId - the operationId as defined in the API definition (e.g. getContext) 42 | // 43 | // Returns: 44 | // 45 | // a Map which contains the set of headers to be included in the REST API request 46 | func GetSdkHeaders(serviceName string, serviceVersion string, operationID string) map[string]string { 47 | sdkHeaders := make(map[string]string) 48 | 49 | sdkHeaders[headerNameSdkAnalytics] = GetSdkAnalyticsHeader(serviceName, serviceVersion, operationID) 50 | 51 | return sdkHeaders 52 | } 53 | 54 | func GetSdkAnalyticsHeader(serviceName string, serviceVersion string, operationID string) string { 55 | return fmt.Sprintf("service_name=%s;service_version=%s;operation_id=%s", 56 | serviceName, serviceVersion, operationID) 57 | } 58 | 59 | func GetComponentInfo() *core.ProblemComponent { 60 | // This should match the module name in go.mod. 61 | return core.NewProblemComponent("github.com/IBM/cloudant-go-sdk", Version) 62 | } 63 | -------------------------------------------------------------------------------- /common/headers_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2024. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | . "github.com/onsi/ginkgo" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | var _ = Describe(`Headers Unit Tests`, func() { 25 | It("Check SDK Analytics header", func() { 26 | var headers = GetSdkHeaders("myService", "v123", "myOperation") 27 | Expect(headers).ToNot(BeNil()) 28 | analyticsHeader, foundIt := headers[headerNameSdkAnalytics] 29 | Expect(foundIt).To(BeTrue()) 30 | Expect(analyticsHeader).To(Equal("service_name=myService;service_version=v123;operation_id=myOperation")) 31 | }) 32 | 33 | It("GetComponentInfo", func() { 34 | var problemComponent = GetComponentInfo() 35 | Expect(problemComponent).ToNot(BeNil()) 36 | Expect(problemComponent.Name).To(Equal("github.com/IBM/cloudant-go-sdk")) 37 | Expect(problemComponent.Version).ToNot(BeNil()) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /common/version.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | // Version of the SDK 20 | const Version = "0.10.3" 21 | -------------------------------------------------------------------------------- /config/header-template.txt: -------------------------------------------------------------------------------- 1 | * 2 | * {{COPYRIGHT}} 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. -------------------------------------------------------------------------------- /examples/snippets/deleteAttachment/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteAttachmentOptions := service.NewDeleteAttachmentOptions( 17 | "products", 18 | "1000042", 19 | "product_details.txt", 20 | ) 21 | deleteAttachmentOptions.SetRev("4-1a0d1cd6f40472509e9aac646183736a") 22 | 23 | documentResult, response, err := service.DeleteAttachment(deleteAttachmentOptions) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | b, _ := json.MarshalIndent(documentResult, "", " ") 29 | fmt.Println(string(b)) 30 | // section: markdown 31 | // This example requires the `product_details.txt` attachment in `1000042` document to exist. To create the attachment, see [Create or modify an attachment.](#putattachment) 32 | -------------------------------------------------------------------------------- /examples/snippets/deleteDatabase/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteDatabaseOptions := service.NewDeleteDatabaseOptions( 17 | "", 18 | ) 19 | 20 | ok, response, err := service.DeleteDatabase(deleteDatabaseOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(ok, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/deleteDesignDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteDesignDocumentOptions := service.NewDeleteDesignDocumentOptions( 17 | "products", 18 | "appliances", 19 | ) 20 | deleteDesignDocumentOptions.SetRev("1-98e6a25b3b45df62e7d47095ac15b16a") 21 | 22 | documentResult, response, err := service.DeleteDesignDocument(deleteDesignDocumentOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(documentResult, "", " ") 28 | fmt.Println(string(b)) 29 | // section: markdown 30 | // This request requires the example revisions in the DELETE body to be replaced with valid revisions. 31 | -------------------------------------------------------------------------------- /examples/snippets/deleteDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteDocumentOptions := service.NewDeleteDocumentOptions( 17 | "orders", 18 | "order00058", 19 | ) 20 | deleteDocumentOptions.SetRev("1-99b02e08da151943c2dcb40090160bb8") 21 | 22 | documentResult, response, err := service.DeleteDocument(deleteDocumentOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(documentResult, "", " ") 28 | fmt.Println(string(b)) 29 | -------------------------------------------------------------------------------- /examples/snippets/deleteIndex/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteIndexOptions := service.NewDeleteIndexOptions( 17 | "users", 18 | "json-index", 19 | "json", 20 | "getUserByName", 21 | ) 22 | 23 | ok, response, err := service.DeleteIndex(deleteIndexOptions) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | b, _ := json.MarshalIndent(ok, "", " ") 29 | fmt.Println(string(b)) 30 | // section: markdown 31 | // This example will fail if `getUserByName` index doesn't exist. To create the index, see [Create a new index on a database.](#postindex) 32 | -------------------------------------------------------------------------------- /examples/snippets/deleteLocalDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteLocalDocumentOptions := service.NewDeleteLocalDocumentOptions( 17 | "orders", 18 | "local-0007741142412418284", 19 | ) 20 | 21 | documentResult, response, err := service.DeleteLocalDocument(deleteLocalDocumentOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(documentResult, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/deleteReplicationDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | deleteReplicationDocumentOptions := service.NewDeleteReplicationDocumentOptions( 17 | "repldoc-example", 18 | ) 19 | deleteReplicationDocumentOptions.SetRev("3-a0ccbdc6fe95b4184f9031d086034d85") 20 | 21 | documentResult, response, err := service.DeleteReplicationDocument(deleteReplicationDocumentOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(documentResult, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/getActiveTasks/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getActiveTasksOptions := service.NewGetActiveTasksOptions() 17 | 18 | activeTask, response, err := service.GetActiveTasks(getActiveTasksOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(activeTask, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getActivityTrackerEvents/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getActivityTrackerEventsOptions := service.NewGetActivityTrackerEventsOptions() 17 | 18 | activityTrackerEvents, response, err := service.GetActivityTrackerEvents(getActivityTrackerEventsOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(activityTrackerEvents, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getAllDbs/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getAllDbsOptions := service.NewGetAllDbsOptions() 17 | 18 | result, response, err := service.GetAllDbs(getAllDbsOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(result, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getAttachment/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | "io" 6 | 7 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | getAttachmentOptions := service.NewGetAttachmentOptions( 18 | "products", 19 | "1000042", 20 | "product_details.txt", 21 | ) 22 | 23 | result, response, err := service.GetAttachment(getAttachmentOptions) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | data, _ := io.ReadAll(result) 29 | fmt.Println("\n", string(data)) 30 | // section: markdown 31 | // This example requires the `product_details.txt` attachment in `1000042` document to exist. To create the attachment, see [Create or modify an attachment.](#putattachment) 32 | -------------------------------------------------------------------------------- /examples/snippets/getCapacityThroughputInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getCapacityThroughputInformationOptions := service.NewGetCapacityThroughputInformationOptions() 17 | 18 | capacityThroughputInformation, response, err := service.GetCapacityThroughputInformation(getCapacityThroughputInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(capacityThroughputInformation, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getCorsInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getCorsInformationOptions := service.NewGetCorsInformationOptions() 17 | 18 | corsConfiguration, response, err := service.GetCorsInformation(getCorsInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(corsConfiguration, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getCurrentThroughputInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getCurrentThroughputInformationOptions := service.NewGetCurrentThroughputInformationOptions() 17 | 18 | currentThroughputInformation, response, err := service.GetCurrentThroughputInformation(getCurrentThroughputInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(currentThroughputInformation, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getDatabaseInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getDatabaseInformationOptions := service.NewGetDatabaseInformationOptions( 17 | "products", 18 | ) 19 | 20 | databaseInformation, response, err := service.GetDatabaseInformation(getDatabaseInformationOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(databaseInformation, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getDbUpdates/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getDbUpdatesOptions := service.NewGetDbUpdatesOptions() 17 | getDbUpdatesOptions.SetFeed("normal") 18 | getDbUpdatesOptions.SetHeartbeat(10000) 19 | getDbUpdatesOptions.SetSince("now") 20 | 21 | dbUpdates, response, err := service.GetDbUpdates(getDbUpdatesOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(dbUpdates, "", " ") 27 | fmt.Println(string(b)) 28 | // section: markdown 29 | // This request requires `server_admin` access. 30 | -------------------------------------------------------------------------------- /examples/snippets/getDesignDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getDesignDocumentOptions := service.NewGetDesignDocumentOptions( 17 | "products", 18 | "appliances", 19 | ) 20 | getDesignDocumentOptions.SetLatest(true) 21 | 22 | designDocument, response, err := service.GetDesignDocument(getDesignDocumentOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(designDocument, "", " ") 28 | fmt.Println(string(b)) 29 | -------------------------------------------------------------------------------- /examples/snippets/getDesignDocumentInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getDesignDocumentInformationOptions := service.NewGetDesignDocumentInformationOptions( 17 | "products", 18 | "appliances", 19 | ) 20 | 21 | designDocumentInformation, response, err := service.GetDesignDocumentInformation(getDesignDocumentInformationOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(designDocumentInformation, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/getDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getDocumentOptions := service.NewGetDocumentOptions( 17 | "products", 18 | "1000042", 19 | ) 20 | 21 | document, response, err := service.GetDocument(getDocumentOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(document, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/getDocumentShardsInfo/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getDocumentShardsInfoOptions := service.NewGetDocumentShardsInfoOptions( 17 | "products", 18 | "1000042", 19 | ) 20 | 21 | documentShardInfo, response, err := service.GetDocumentShardsInfo(getDocumentShardsInfoOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(documentShardInfo, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/getIndexesInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getIndexesInformationOptions := service.NewGetIndexesInformationOptions( 17 | "users", 18 | ) 19 | 20 | indexesInformation, response, err := service.GetIndexesInformation(getIndexesInformationOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(indexesInformation, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getLocalDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getLocalDocumentOptions := service.NewGetLocalDocumentOptions( 17 | "orders", 18 | "local-0007741142412418284", 19 | ) 20 | 21 | document, response, err := service.GetLocalDocument(getLocalDocumentOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(document, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/getMembershipInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getMembershipInformationOptions := service.NewGetMembershipInformationOptions() 17 | 18 | membershipInformation, response, err := service.GetMembershipInformation(getMembershipInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(membershipInformation, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getPartitionInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getPartitionInformationOptions := service.NewGetPartitionInformationOptions( 17 | "events", 18 | "ns1HJS13AMkK", 19 | ) 20 | 21 | partitionInformation, response, err := service.GetPartitionInformation(getPartitionInformationOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(partitionInformation, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/getReplicationDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getReplicationDocumentOptions := service.NewGetReplicationDocumentOptions( 17 | "repldoc-example", 18 | ) 19 | 20 | replicationDocument, response, err := service.GetReplicationDocument(getReplicationDocumentOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(replicationDocument, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getSchedulerDocs/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSchedulerDocsOptions := service.NewGetSchedulerDocsOptions() 17 | getSchedulerDocsOptions.SetLimit(100) 18 | getSchedulerDocsOptions.SetStates([]string{"completed"}) 19 | 20 | schedulerDocsResult, response, err := service.GetSchedulerDocs(getSchedulerDocsOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(schedulerDocsResult, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getSchedulerDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSchedulerDocumentOptions := service.NewGetSchedulerDocumentOptions( 17 | "repldoc-example", 18 | ) 19 | 20 | schedulerDocument, response, err := service.GetSchedulerDocument(getSchedulerDocumentOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(schedulerDocument, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getSchedulerJob/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSchedulerJobOptions := service.NewGetSchedulerJobOptions( 17 | "7b94915cd8c4a0173c77c55cd0443939+continuous", 18 | ) 19 | 20 | schedulerJob, response, err := service.GetSchedulerJob(getSchedulerJobOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(schedulerJob, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getSchedulerJobs/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSchedulerJobsOptions := service.NewGetSchedulerJobsOptions() 17 | getSchedulerJobsOptions.SetLimit(100) 18 | 19 | schedulerJobsResult, response, err := service.GetSchedulerJobs(getSchedulerJobsOptions) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | b, _ := json.MarshalIndent(schedulerJobsResult, "", " ") 25 | fmt.Println(string(b)) 26 | -------------------------------------------------------------------------------- /examples/snippets/getSearchInfo/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSearchInfoOptions := service.NewGetSearchInfoOptions( 17 | "events", 18 | "checkout", 19 | "findByDate", 20 | ) 21 | 22 | searchInfoResult, response, err := service.GetSearchInfo(getSearchInfoOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(searchInfoResult, "", " ") 28 | fmt.Println(string(b)) 29 | // section: markdown 30 | // This example requires the `findByDate` Cloudant Search partitioned index to exist. To create the design document with this index, see [Create or modify a design document.](#putdesigndocument) 31 | -------------------------------------------------------------------------------- /examples/snippets/getSecurity/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSecurityOptions := service.NewGetSecurityOptions( 17 | "products", 18 | ) 19 | 20 | security, response, err := service.GetSecurity(getSecurityOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(security, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getServerInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getServerInformationOptions := service.NewGetServerInformationOptions() 17 | 18 | serverInformation, response, err := service.GetServerInformation(getServerInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(serverInformation, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getSessionInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getSessionInformationOptions := service.NewGetSessionInformationOptions() 17 | 18 | sessionInformation, response, err := service.GetSessionInformation(getSessionInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(sessionInformation, "", " ") 24 | fmt.Println(string(b)) 25 | // section: markdown 26 | // For more details on Session Authentication, see [Authentication.](#authentication) 27 | -------------------------------------------------------------------------------- /examples/snippets/getShardsInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getShardsInformationOptions := service.NewGetShardsInformationOptions( 17 | "products", 18 | ) 19 | 20 | shardsInformation, response, err := service.GetShardsInformation(getShardsInformationOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(shardsInformation, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/getUpInformation/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getUpInformationOptions := service.NewGetUpInformationOptions() 17 | 18 | upInformation, response, err := service.GetUpInformation(getUpInformationOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(upInformation, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/getUuids/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | getUuidsOptions := service.NewGetUuidsOptions() 17 | getUuidsOptions.SetCount(10) 18 | 19 | uuidsResult, response, err := service.GetUuids(getUuidsOptions) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | b, _ := json.MarshalIndent(uuidsResult, "", " ") 25 | fmt.Println(string(b)) 26 | -------------------------------------------------------------------------------- /examples/snippets/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/IBM/cloudant-go-sdk/examples/snippets 2 | 3 | go 1.22.5 4 | -------------------------------------------------------------------------------- /examples/snippets/headAttachment/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | headAttachmentOptions := service.NewHeadAttachmentOptions( 17 | "products", 18 | "1000042", 19 | "product_details.txt", 20 | ) 21 | 22 | response, err := service.HeadAttachment(headAttachmentOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | fmt.Println(response.StatusCode) 28 | fmt.Println(response.Headers["Content-Length"]) 29 | fmt.Println(response.Headers["Content-Type"]) 30 | // section: markdown 31 | // This example requires the `product_details.txt` attachment in `1000042` document to exist. To create the attachment, see [Create or modify an attachment.](#putattachment) 32 | -------------------------------------------------------------------------------- /examples/snippets/headDatabase/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | headDatabaseOptions := service.NewHeadDatabaseOptions( 17 | "products", 18 | ) 19 | 20 | response, err := service.HeadDatabase(headDatabaseOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | fmt.Println(response.StatusCode) 26 | -------------------------------------------------------------------------------- /examples/snippets/headDesignDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | headDesignDocumentOptions := service.NewHeadDesignDocumentOptions( 17 | "events", 18 | "checkout", 19 | ) 20 | 21 | response, err := service.HeadDesignDocument(headDesignDocumentOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | fmt.Println(response.StatusCode) 27 | fmt.Println(response.Headers["ETag"]) 28 | -------------------------------------------------------------------------------- /examples/snippets/headDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | headDocumentOptions := service.NewHeadDocumentOptions( 17 | "orders", 18 | "order00058", 19 | ) 20 | 21 | response, err := service.HeadDocument(headDocumentOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | fmt.Println(response.StatusCode) 27 | fmt.Println(response.Headers["ETag"]) 28 | -------------------------------------------------------------------------------- /examples/snippets/headReplicationDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | headReplicationDocumentOptions := service.NewHeadReplicationDocumentOptions( 17 | "repldoc-example", 18 | ) 19 | 20 | response, err := service.HeadReplicationDocument(headReplicationDocumentOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | fmt.Println(response.StatusCode) 26 | fmt.Println(response.Headers["ETag"]) 27 | -------------------------------------------------------------------------------- /examples/snippets/headSchedulerJob/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | headSchedulerJobOptions := service.NewHeadSchedulerJobOptions( 17 | "7b94915cd8c4a0173c77c55cd0443939+continuous", 18 | ) 19 | 20 | response, err := service.HeadSchedulerJob(headSchedulerJobOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | fmt.Println(response.StatusCode) 26 | -------------------------------------------------------------------------------- /examples/snippets/postActivityTrackerEvents/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postActivityTrackerEventsOptions := service.NewPostActivityTrackerEventsOptions( 17 | []string{"management"}, 18 | ) 19 | 20 | activityTrackerEvents, response, err := service.PostActivityTrackerEvents(postActivityTrackerEventsOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(activityTrackerEvents, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/postAllDocs/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postAllDocsOptions := service.NewPostAllDocsOptions( 17 | "orders", 18 | ) 19 | postAllDocsOptions.SetIncludeDocs(true) 20 | postAllDocsOptions.SetStartKey("abc") 21 | postAllDocsOptions.SetLimit(10) 22 | 23 | allDocsResult, response, err := service.PostAllDocs(postAllDocsOptions) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | b, _ := json.MarshalIndent(allDocsResult, "", " ") 29 | fmt.Println(string(b)) 30 | -------------------------------------------------------------------------------- /examples/snippets/postAllDocs/example_request_as_a_stream.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | "io" 6 | "os" 7 | 8 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 9 | ) 10 | // section: code 11 | service, err := cloudantv1.NewCloudantV1( 12 | &cloudantv1.CloudantV1Options{}, 13 | ) 14 | if err != nil { 15 | panic(err) 16 | } 17 | 18 | postAllDocsOptions := service.NewPostAllDocsOptions( 19 | "orders", 20 | ) 21 | postAllDocsOptions.SetIncludeDocs(true) 22 | postAllDocsOptions.SetStartKey("abc") 23 | postAllDocsOptions.SetLimit(10) 24 | 25 | allDocsResult, response, err := service.PostAllDocsAsStream(postAllDocsOptions) 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | if allDocsResult != nil { 31 | defer allDocsResult.Close() 32 | outFile, err := os.Create("result.json") 33 | if err != nil { 34 | panic(err) 35 | } 36 | defer outFile.Close() 37 | if _, err = io.Copy(outFile, allDocsResult); err != nil { 38 | panic(err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/snippets/postAllDocsQueries/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | allDocsQueries := []cloudantv1.AllDocsQuery{ 18 | { 19 | Keys: []string{ 20 | "1000042", 21 | "1000043", 22 | }, 23 | }, 24 | { 25 | Limit: core.Int64Ptr(3), 26 | Skip: core.Int64Ptr(2), 27 | }, 28 | } 29 | postAllDocsQueriesOptions := service.NewPostAllDocsQueriesOptions( 30 | "products", 31 | allDocsQueries, 32 | ) 33 | 34 | allDocsQueriesResult, response, err := service.PostAllDocsQueries(postAllDocsQueriesOptions) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | b, _ := json.MarshalIndent(allDocsQueriesResult, "", " ") 40 | fmt.Println(string(b)) 41 | -------------------------------------------------------------------------------- /examples/snippets/postApiKeys/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postApiKeysOptions := service.NewPostApiKeysOptions() 17 | 18 | apiKeysResult, response, err := service.PostApiKeys(postApiKeysOptions) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | b, _ := json.MarshalIndent(apiKeysResult, "", " ") 24 | fmt.Println(string(b)) 25 | -------------------------------------------------------------------------------- /examples/snippets/postBulkDocs/example_request_as_a_stream.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | "os" 6 | 7 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | file, err := os.Open("upload.json") 18 | if err != nil { 19 | panic(err) 20 | } 21 | 22 | postBulkDocsOptions := service.NewPostBulkDocsOptions( 23 | "events", 24 | ) 25 | 26 | postBulkDocsOptions.SetBody(file) 27 | 28 | documentResult, response, err := service.PostBulkDocs(postBulkDocsOptions) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | b, _ := json.MarshalIndent(documentResult, "", " ") 34 | fmt.Println(string(b)) 35 | // section: markdown 36 | // Content of upload.json 37 | // section: code 38 | { 39 | "docs": [ 40 | { 41 | "_id": "ns1HJS13AMkK:0007241142412418284", 42 | "type": "event", 43 | "userId": "abc123", 44 | "eventType": "addedToBasket", 45 | "productId": "1000042", 46 | "date": "2019-01-28T10:44:22.000Z" 47 | }, 48 | { 49 | "_id": "H8tDIwfadxp9:0007241142412418285", 50 | "type": "event", 51 | "userId": "abc234", 52 | "eventType": "addedToBasket", 53 | "productId": "1000050", 54 | "date": "2019-01-25T20:00:00.000Z" 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /examples/snippets/postBulkDocs/example_request_create_documents.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | eventDoc1 := cloudantv1.Document{ 18 | ID: core.StringPtr("ns1HJS13AMkK:0007241142412418284"), 19 | } 20 | eventDoc1.SetProperty("type", "event") 21 | eventDoc1.SetProperty("userId", "abc123") 22 | eventDoc1.SetProperty("eventType", "addedToBasket") 23 | eventDoc1.SetProperty("productId", "1000042") 24 | eventDoc1.SetProperty("date", "2019-01-28T10:44:22.000Z") 25 | 26 | eventDoc2 := cloudantv1.Document{ 27 | ID: core.StringPtr("H8tDIwfadxp9:0007241142412418285"), 28 | } 29 | eventDoc2.SetProperty("type", "event") 30 | eventDoc2.SetProperty("userId", "abc234") 31 | eventDoc2.SetProperty("eventType", "addedToBasket") 32 | eventDoc2.SetProperty("productId", "1000050") 33 | eventDoc2.SetProperty("date", "2019-01-25T20:00:00.000Z") 34 | 35 | postBulkDocsOptions := service.NewPostBulkDocsOptions( 36 | "events", 37 | ) 38 | bulkDocs, err := service.NewBulkDocs( 39 | []cloudantv1.Document{ 40 | eventDoc1, 41 | eventDoc2, 42 | }, 43 | ) 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | postBulkDocsOptions.SetBulkDocs(bulkDocs) 49 | 50 | documentResult, response, err := service.PostBulkDocs(postBulkDocsOptions) 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | b, _ := json.MarshalIndent(documentResult, "", " ") 56 | fmt.Println(string(b)) 57 | -------------------------------------------------------------------------------- /examples/snippets/postBulkDocs/example_request_delete_documents.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | eventDoc1 := cloudantv1.Document{ 18 | ID: core.StringPtr("ns1HJS13AMkK:0007241142412418284"), 19 | } 20 | eventDoc1.Rev = core.StringPtr("1-5005d65514fe9e90f8eccf174af5dd64") 21 | eventDoc1.Deleted = core.BoolPtr(true) 22 | 23 | eventDoc2 := cloudantv1.Document{ 24 | ID: core.StringPtr("H8tDIwfadxp9:0007241142412418285"), 25 | } 26 | eventDoc2.Rev = core.StringPtr("1-2d7810b054babeda4812b3924428d6d6") 27 | eventDoc2.Deleted = core.BoolPtr(true) 28 | 29 | postBulkDocsOptions := service.NewPostBulkDocsOptions( 30 | "events", 31 | ) 32 | bulkDocs, err := service.NewBulkDocs( 33 | []cloudantv1.Document{ 34 | eventDoc1, 35 | eventDoc2, 36 | }, 37 | ) 38 | if err != nil { 39 | panic(err) 40 | } 41 | 42 | postBulkDocsOptions.SetBulkDocs(bulkDocs) 43 | 44 | documentResult, response, err := service.PostBulkDocs(postBulkDocsOptions) 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | b, _ := json.MarshalIndent(documentResult, "", " ") 50 | fmt.Println(string(b)) 51 | -------------------------------------------------------------------------------- /examples/snippets/postBulkGet/alternative_example_request_for_atts_since.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | docID := "order00058" 17 | 18 | postBulkGetOptions := service.NewPostBulkGetOptions( 19 | "orders", 20 | []cloudantv1.BulkGetQueryDocument{ 21 | { 22 | ID: &docID, 23 | AttsSince: []string{"1-99b02e08da151943c2dcb40090160bb8"}, 24 | }, 25 | }, 26 | ) 27 | 28 | bulkGetResult, response, err := service.PostBulkGet(postBulkGetOptions) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | b, _ := json.MarshalIndent(bulkGetResult, "", " ") 34 | fmt.Println(string(b)) 35 | -------------------------------------------------------------------------------- /examples/snippets/postBulkGet/alternative_example_request_for_open_revs_all.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | postBulkGetOptions := service.NewPostBulkGetOptions( 18 | "orders", 19 | []cloudantv1.BulkGetQueryDocument{{ID: core.StringPtr("order00067")}}, 20 | ) 21 | 22 | bulkGetResult, response, err := service.PostBulkGet(postBulkGetOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(bulkGetResult, "", " ") 28 | fmt.Println(string(b)) 29 | -------------------------------------------------------------------------------- /examples/snippets/postBulkGet/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | docID := "order00067" 18 | 19 | bulkGetDocs := []cloudantv1.BulkGetQueryDocument{ 20 | { 21 | ID: &docID, 22 | Rev: core.StringPtr("3-917fa2381192822767f010b95b45325b"), 23 | }, 24 | { 25 | ID: &docID, 26 | Rev: core.StringPtr("4-a5be949eeb7296747cc271766e9a498b"), 27 | }, 28 | } 29 | 30 | postBulkGetOptions := service.NewPostBulkGetOptions( 31 | "orders", 32 | bulkGetDocs, 33 | ) 34 | bulkGetResult, response, err := service.PostBulkGet(postBulkGetOptions) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | b, _ := json.MarshalIndent(bulkGetResult, "", " ") 40 | fmt.Println(string(b)) 41 | -------------------------------------------------------------------------------- /examples/snippets/postChanges/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postChangesOptions := service.NewPostChangesOptions( 17 | "orders", 18 | ) 19 | 20 | changesResult, response, err := service.PostChanges(postChangesOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(changesResult, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/postChanges/example_request_as_a_stream.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | "io" 6 | "os" 7 | 8 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 9 | ) 10 | // section: code 11 | service, err := cloudantv1.NewCloudantV1( 12 | &cloudantv1.CloudantV1Options{}, 13 | ) 14 | if err != nil { 15 | panic(err) 16 | } 17 | 18 | postChangesOptions := service.NewPostChangesOptions( 19 | "orders", 20 | ) 21 | 22 | changesResult, response, err := service.PostChangesAsStream(postChangesOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | if changesResult != nil { 28 | defer changesResult.Close() 29 | outFile, err := os.Create("result.json") 30 | if err != nil { 31 | panic(err) 32 | } 33 | defer outFile.Close() 34 | if _, err = io.Copy(outFile, changesResult); err != nil { 35 | panic(err) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/snippets/postDbsInfo/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postDbsInfoOptions := service.NewPostDbsInfoOptions([]string{ 17 | "products", 18 | "users", 19 | "orders", 20 | }) 21 | 22 | dbsInfoResult, response, err := service.PostDbsInfo(postDbsInfoOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(dbsInfoResult, "", " ") 28 | fmt.Println(string(b)) 29 | -------------------------------------------------------------------------------- /examples/snippets/postDesignDocs/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postDesignDocsOptions := service.NewPostDesignDocsOptions( 17 | "users", 18 | ) 19 | postDesignDocsOptions.SetAttachments(true) 20 | 21 | allDocsResult, response, err := service.PostDesignDocs(postDesignDocsOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(allDocsResult, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/postDesignDocsQueries/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | doc1 := cloudantv1.AllDocsQuery{ 18 | Descending: core.BoolPtr(true), 19 | IncludeDocs: core.BoolPtr(true), 20 | Limit: core.Int64Ptr(10), 21 | } 22 | 23 | doc2 := cloudantv1.AllDocsQuery{ 24 | InclusiveEnd: core.BoolPtr(true), 25 | Key: core.StringPtr("_design/allusers"), 26 | Skip: core.Int64Ptr(1), 27 | } 28 | 29 | postDesignDocsQueriesOptions := service.NewPostDesignDocsQueriesOptions( 30 | "users", 31 | []cloudantv1.AllDocsQuery{ 32 | doc1, 33 | doc2, 34 | }, 35 | ) 36 | 37 | allDocsQueriesResult, response, err := service.PostDesignDocsQueries(postDesignDocsQueriesOptions) 38 | if err != nil { 39 | panic(err) 40 | } 41 | 42 | b, _ := json.MarshalIndent(allDocsQueriesResult, "", " ") 43 | fmt.Println(string(b)) 44 | -------------------------------------------------------------------------------- /examples/snippets/postDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | productsDoc := cloudantv1.Document{ 18 | ID: core.StringPtr("1000042"), 19 | } 20 | productsDoc.SetProperty("type", "product") 21 | productsDoc.SetProperty("productId", "1000042") 22 | productsDoc.SetProperty("brand", "Salter") 23 | productsDoc.SetProperty("name", "Digital Kitchen Scales") 24 | productsDoc.SetProperty("description", "Slim Colourful Design Electronic Cooking Appliance for Home / Kitchen, Weigh up to 5kg + Aquatronic for Liquids ml + fl. oz. 15Yr Guarantee - Green") 25 | productsDoc.SetProperty("price", 14.99) 26 | productsDoc.SetProperty("image", "assets/img/0gmsnghhew.jpg") 27 | 28 | postDocumentOptions := service.NewPostDocumentOptions( 29 | "products", 30 | ) 31 | postDocumentOptions.SetDocument(&productsDoc) 32 | 33 | documentResult, response, err := service.PostDocument(postDocumentOptions) 34 | if err != nil { 35 | panic(err) 36 | } 37 | 38 | b, _ := json.MarshalIndent(documentResult, "", " ") 39 | fmt.Println(string(b)) 40 | -------------------------------------------------------------------------------- /examples/snippets/postExplain/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postExplainOptions := service.NewPostExplainOptions( 17 | "users", 18 | map[string]interface{}{ 19 | "type": map[string]string{ 20 | "$eq": "user", 21 | }, 22 | }, 23 | ) 24 | postExplainOptions.SetExecutionStats(true) 25 | postExplainOptions.SetLimit(10) 26 | 27 | explainResult, response, err := service.PostExplain(postExplainOptions) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | b, _ := json.MarshalIndent(explainResult, "", " ") 33 | fmt.Println(string(b)) 34 | -------------------------------------------------------------------------------- /examples/snippets/postFind/example_request_for_json_index_type.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postFindOptions := service.NewPostFindOptions( 17 | "users", 18 | map[string]interface{}{ 19 | "email_verified": map[string]bool{ 20 | "$eq": true, 21 | }, 22 | }, 23 | ) 24 | postFindOptions.SetFields( 25 | []string{"_id", "type", "name", "email"}, 26 | ) 27 | postFindOptions.SetSort([]map[string]string{{"email": "desc"}}) 28 | postFindOptions.SetLimit(3) 29 | 30 | findResult, response, err := service.PostFind(postFindOptions) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | b, _ := json.MarshalIndent(findResult, "", " ") 36 | fmt.Println(string(b)) 37 | // section: markdown 38 | // This example requires the `getUserByEmail` Cloudant Query "json" index to exist. To create the index, see [Create a new index on a database.](#postindex) 39 | -------------------------------------------------------------------------------- /examples/snippets/postFind/example_request_for_text_index_type.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postFindOptions := service.NewPostFindOptions( 17 | "users", 18 | map[string]interface{}{ 19 | "address": map[string]string{ 20 | "$regex": "Street", 21 | }, 22 | }, 23 | ) 24 | postFindOptions.SetFields( 25 | []string{"_id", "type", "name", "email", "address"}, 26 | ) 27 | postFindOptions.SetLimit(3) 28 | 29 | findResult, response, err := service.PostFind(postFindOptions) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | b, _ := json.MarshalIndent(findResult, "", " ") 35 | fmt.Println(string(b)) 36 | // section: markdown 37 | // This example requires the `getUserByAddress` Cloudant Query "text" index to exist. To create the index, see [Create a new index on a database.](#postindex) 38 | -------------------------------------------------------------------------------- /examples/snippets/postIndex/example_request_using_json_type_index.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | // Type "json" index fields require an object that maps the name of a field to a sort direction. 18 | var indexField cloudantv1.IndexField 19 | indexField.SetProperty("email", core.StringPtr("asc")) 20 | 21 | postIndexOptions := service.NewPostIndexOptions( 22 | "users", 23 | &cloudantv1.IndexDefinition{ 24 | Fields: []cloudantv1.IndexField{ 25 | indexField, 26 | }, 27 | }, 28 | ) 29 | postIndexOptions.SetDdoc("json-index") 30 | postIndexOptions.SetName("getUserByEmail") 31 | postIndexOptions.SetType("json") 32 | 33 | indexResult, response, err := service.PostIndex(postIndexOptions) 34 | if err != nil { 35 | panic(err) 36 | } 37 | 38 | b, _ := json.MarshalIndent(indexResult, "", " ") 39 | fmt.Println(string(b)) 40 | -------------------------------------------------------------------------------- /examples/snippets/postIndex/example_request_using_text_type_index.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | // Type "text" index fields require an object with a name and type properties for the field. 18 | var indexField cloudantv1.IndexField 19 | indexField.SetProperty("name", core.StringPtr("address")) 20 | indexField.SetProperty("type", core.StringPtr("string")) 21 | 22 | postIndexOptions := service.NewPostIndexOptions( 23 | "users", 24 | &cloudantv1.IndexDefinition{ 25 | Fields: []cloudantv1.IndexField{ 26 | indexField, 27 | }, 28 | }, 29 | ) 30 | postIndexOptions.SetDdoc("text-index") 31 | postIndexOptions.SetName("getUserByAddress") 32 | postIndexOptions.SetType("text") 33 | 34 | indexResult, response, err := service.PostIndex(postIndexOptions) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | b, _ := json.MarshalIndent(indexResult, "", " ") 40 | fmt.Println(string(b)) 41 | -------------------------------------------------------------------------------- /examples/snippets/postPartitionAllDocs/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postPartitionAllDocsOptions := service.NewPostPartitionAllDocsOptions( 17 | "events", 18 | "ns1HJS13AMkK", 19 | ) 20 | postPartitionAllDocsOptions.SetIncludeDocs(true) 21 | 22 | allDocsResult, response, err := service.PostPartitionAllDocs(postPartitionAllDocsOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(allDocsResult, "", " ") 28 | fmt.Println(string(b)) 29 | -------------------------------------------------------------------------------- /examples/snippets/postPartitionExplain/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | selector := map[string]interface{}{ 17 | "userId": map[string]string{ 18 | "$eq": "abc123", 19 | }, 20 | } 21 | 22 | postPartitionExplainOptions := service.NewPostPartitionExplainOptions( 23 | "events", 24 | "ns1HJS13AMkK", 25 | selector, 26 | ) 27 | postExplainOptions.SetExecutionStats(true) 28 | postExplainOptions.SetLimit(10) 29 | 30 | 31 | explainResult, response, err := service.PostPartitionExplain(postPartitionExplainOptions) 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | b, _ := json.MarshalIndent(explainResult, "", " ") 37 | fmt.Println(string(b)) 38 | -------------------------------------------------------------------------------- /examples/snippets/postPartitionFind/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | selector := map[string]interface{}{ 17 | "userId": map[string]string{ 18 | "$eq": "abc123", 19 | }, 20 | } 21 | 22 | postPartitionFindOptions := service.NewPostPartitionFindOptions( 23 | "events", 24 | "ns1HJS13AMkK", 25 | selector, 26 | ) 27 | postPartitionFindOptions.SetFields([]string{ 28 | "productId", "eventType", "date", 29 | }) 30 | 31 | findResult, response, err := service.PostPartitionFind(postPartitionFindOptions) 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | b, _ := json.MarshalIndent(findResult, "", " ") 37 | fmt.Println(string(b)) 38 | -------------------------------------------------------------------------------- /examples/snippets/postPartitionSearch/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postPartitionSearchOptions := service.NewPostPartitionSearchOptions( 17 | "events", 18 | "ns1HJS13AMkK", 19 | "checkout", 20 | "findByDate", 21 | "date:[2019-01-01T12:00:00.000Z TO 2019-01-31T12:00:00.000Z]", 22 | ) 23 | 24 | searchResult, response, err := service.PostPartitionSearch(postPartitionSearchOptions) 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | b, _ := json.MarshalIndent(searchResult, "", " ") 30 | fmt.Println(string(b)) 31 | // section: markdown 32 | // This example requires the `findByDate` Cloudant Search partitioned index to exist. To create the design document with this index, see [Create or modify a design document.](#putdesigndocument) 33 | -------------------------------------------------------------------------------- /examples/snippets/postPartitionView/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postPartitionViewOptions := service.NewPostPartitionViewOptions( 17 | "events", 18 | "ns1HJS13AMkK", 19 | "checkout", 20 | "byProductId", 21 | ) 22 | postPartitionViewOptions.SetIncludeDocs(true) 23 | postPartitionViewOptions.SetLimit(10) 24 | 25 | viewResult, response, err := service.PostPartitionView(postPartitionViewOptions) 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | b, _ := json.MarshalIndent(viewResult, "", " ") 31 | fmt.Println(string(b)) 32 | // section: markdown 33 | // This example requires the `byProductId` partitioned view to exist. To create the view, see [Create or modify a design document.](#putdesigndocument) 34 | -------------------------------------------------------------------------------- /examples/snippets/postRevsDiff/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postRevsDiffOptions := service.NewPostRevsDiffOptions( 17 | "orders", 18 | map[string][]string{ 19 | "order00077": { 20 | "<1-missing-revision>", 21 | "<2-missing-revision>", 22 | "<3-possible-ancestor-revision>", 23 | }, 24 | }, 25 | ) 26 | 27 | mapStringRevsDiff, response, err := service.PostRevsDiff(postRevsDiffOptions) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | b, _ := json.MarshalIndent(mapStringRevsDiff, "", " ") 33 | fmt.Println(string(b)) 34 | // section: markdown 35 | // This example requires the example revisions in the POST body to be replaced with valid revisions. 36 | -------------------------------------------------------------------------------- /examples/snippets/postSearch/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postSearchOptions := service.NewPostSearchOptions( 17 | "users", 18 | "allusers", 19 | "activeUsers", 20 | "name:Jane* AND active:True", 21 | ) 22 | 23 | searchResult, response, err := service.PostSearch(postSearchOptions) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | b, _ := json.MarshalIndent(searchResult, "", " ") 29 | fmt.Println(string(b)) 30 | // section: markdown 31 | // This example requires the `activeUsers` Cloudant Search index to exist. To create the design document with this index, see [Create or modify a design document.](#putdesigndocument) 32 | -------------------------------------------------------------------------------- /examples/snippets/postSearchAnalyze/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postSearchAnalyzeOptions := service.NewPostSearchAnalyzeOptions( 17 | "english", 18 | "running is fun", 19 | ) 20 | 21 | searchAnalyzeResult, response, err := service.PostSearchAnalyze(postSearchAnalyzeOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(searchAnalyzeResult, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/postView/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | postViewOptions := service.NewPostViewOptions( 17 | "users", 18 | "allusers", 19 | "getVerifiedEmails", 20 | ) 21 | 22 | viewResult, response, err := service.PostView(postViewOptions) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | b, _ := json.MarshalIndent(viewResult, "", " ") 28 | fmt.Println(string(b)) 29 | // section: markdown 30 | // This example requires the `getVerifiedEmails` view to exist. To create the design document with this view, see [Create or modify a design document.](#putdesigndocument) 31 | -------------------------------------------------------------------------------- /examples/snippets/postViewQueries/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | postViewQueriesOptions := service.NewPostViewQueriesOptions( 18 | "users", 19 | "allusers", 20 | "getVerifiedEmails", 21 | []cloudantv1.ViewQuery{ 22 | { 23 | IncludeDocs: core.BoolPtr(true), 24 | Limit: core.Int64Ptr(5), 25 | }, 26 | { 27 | Descending: core.BoolPtr(true), 28 | Skip: core.Int64Ptr(1), 29 | }, 30 | }, 31 | ) 32 | 33 | viewQueriesResult, response, err := service.PostViewQueries(postViewQueriesOptions) 34 | if err != nil { 35 | panic(err) 36 | } 37 | 38 | b, _ := json.MarshalIndent(viewQueriesResult, "", " ") 39 | fmt.Println(string(b)) 40 | // section: markdown 41 | // This example requires the `getVerifiedEmails` view to exist. To create the design document with this view, see [Create or modify a design document.](#putdesigndocument) 42 | -------------------------------------------------------------------------------- /examples/snippets/putAttachment/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "bytes" 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | 8 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 9 | ) 10 | // section: code 11 | service, err := cloudantv1.NewCloudantV1( 12 | &cloudantv1.CloudantV1Options{}, 13 | ) 14 | if err != nil { 15 | panic(err) 16 | } 17 | 18 | putAttachmentOptions := service.NewPutAttachmentOptions( 19 | "products", 20 | "1000042", 21 | "product_details.txt", 22 | io.NopCloser( 23 | bytes.NewReader([]byte("This appliance includes...")), 24 | ), 25 | "text/plain", 26 | ) 27 | 28 | documentResult, response, err := service.PutAttachment(putAttachmentOptions) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | b, _ := json.MarshalIndent(documentResult, "", " ") 34 | fmt.Println(string(b)) 35 | -------------------------------------------------------------------------------- /examples/snippets/putCapacityThroughputConfiguration/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | putCapacityThroughputConfigurationOptions := service.NewPutCapacityThroughputConfigurationOptions( 17 | 1, 18 | ) 19 | 20 | capacityThroughputConfiguration, response, err := service.PutCapacityThroughputConfiguration(putCapacityThroughputConfigurationOptions) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | b, _ := json.MarshalIndent(capacityThroughputConfiguration, "", " ") 26 | fmt.Println(string(b)) 27 | -------------------------------------------------------------------------------- /examples/snippets/putCloudantSecurity/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | putCloudantSecurityConfigurationOptions := service.NewPutCloudantSecurityConfigurationOptions( 17 | "products", 18 | map[string][]string{ 19 | "nobody": {cloudantv1.SecurityCloudantReaderConst}, 20 | }, 21 | ) 22 | 23 | ok, response, err := service.PutCloudantSecurityConfiguration(putCloudantSecurityConfigurationOptions) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | b, _ := json.MarshalIndent(ok, "", " ") 29 | fmt.Println(string(b)) 30 | // section: markdown 31 | // The `nobody` username applies to all unauthenticated connection attempts. For example, if an application tries to read data from a database, but didn't identify itself, the task can continue only if the `nobody` user has the role `_reader`. 32 | // section: markdown 33 | // If instead of using Cloudant's security model for managing permissions you opt to use the Apache CouchDB `_users` database (that is using legacy credentials _and_ the `couchdb_auth_only:true` option) then be aware that the user must already exist in `_users` database before adding permissions. For information on the `_users` database, see Using the `_users` database with Cloudant. 34 | -------------------------------------------------------------------------------- /examples/snippets/putCorsConfiguration/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | putCorsConfigurationOptions := service.NewPutCorsConfigurationOptions([]string{ 17 | "https://example.com", 18 | }) 19 | putCorsConfigurationOptions.SetEnableCors(true) 20 | 21 | ok, response, err := service.PutCorsConfiguration(putCorsConfigurationOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(ok, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/putDatabase/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | putDatabaseOptions := service.NewPutDatabaseOptions( 17 | "events", 18 | ) 19 | putDatabaseOptions.SetPartitioned(true) 20 | 21 | ok, response, err := service.PutDatabase(putDatabaseOptions) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | b, _ := json.MarshalIndent(ok, "", " ") 27 | fmt.Println(string(b)) 28 | -------------------------------------------------------------------------------- /examples/snippets/putDesignDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | emailViewMapReduce, err := service.NewDesignDocumentViewsMapReduce("function(doc) { if(doc.email_verified === true) { emit(doc.email, [doc.name, doc.email_verified, doc.joined]); }}") 17 | if err != nil { 18 | panic(err) 19 | } 20 | 21 | userIndexDefinition, err := service.NewSearchIndexDefinition("function(doc) { index(\"name\", doc.name); index(\"active\", doc.active); }") 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | designDocument := &cloudantv1.DesignDocument{ 27 | Views: map[string]cloudantv1.DesignDocumentViewsMapReduce{ 28 | "getVerifiedEmails": *emailViewMapReduce, 29 | }, 30 | Indexes: map[string]cloudantv1.SearchIndexDefinition{ 31 | "activeUsers": *userIndexDefinition, 32 | }, 33 | } 34 | 35 | putDesignDocumentOptions := service.NewPutDesignDocumentOptions( 36 | "users", 37 | "allusers", 38 | designDocument, 39 | ) 40 | 41 | documentResult, response, err := service.PutDesignDocument(putDesignDocumentOptions) 42 | if err != nil { 43 | panic(err) 44 | } 45 | 46 | b, _ := json.MarshalIndent(documentResult, "", " ") 47 | fmt.Println(string(b)) 48 | 49 | applianceProdIdViewMapReduce, err := service.NewDesignDocumentViewsMapReduce("function(doc) { emit(doc.productId, [doc.date, doc.eventType, doc.userId]); }") 50 | if err != nil { 51 | panic(err) 52 | } 53 | 54 | dateIndexDefinition, err := service.NewSearchIndexDefinition("function(doc) { index(\"date\", doc.date); }") 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | partitionedDesignDocument := &cloudantv1.DesignDocument{ 60 | Views: map[string]cloudantv1.DesignDocumentViewsMapReduce{ 61 | "byProductId": *applianceProdIdViewMapReduce, 62 | }, 63 | Indexes: map[string]cloudantv1.SearchIndexDefinition{ 64 | "findByDate": *dateIndexDefinition, 65 | }, 66 | } 67 | 68 | putPartitionedDesignDocumentOptions := service.NewPutDesignDocumentOptions( 69 | "events", 70 | "checkout", 71 | partitionedDesignDocument, 72 | ) 73 | 74 | documentResult, response, err = service.PutDesignDocument(putPartitionedDesignDocumentOptions) 75 | if err != nil { 76 | panic(err) 77 | } 78 | 79 | b, _ = json.MarshalIndent(documentResult, "", " ") 80 | fmt.Println(string(b)) 81 | // section: markdown 82 | // This example creates `allusers` design document in the `users` database and `checkout` design document in the partitioned `events` database. 83 | -------------------------------------------------------------------------------- /examples/snippets/putDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | eventDoc := cloudantv1.Document{} 17 | eventDoc.SetProperty("type", "event") 18 | eventDoc.SetProperty("userId", "abc123") 19 | eventDoc.SetProperty("eventType", "addedToBasket") 20 | eventDoc.SetProperty("productId", "1000042") 21 | eventDoc.SetProperty("date", "2019-01-28T10:44:22.000Z") 22 | 23 | putDocumentOptions := service.NewPutDocumentOptions( 24 | "events", 25 | "ns1HJS13AMkK:0007241142412418284", 26 | ) 27 | putDocumentOptions.SetDocument(&eventDoc) 28 | 29 | documentResult, response, err := service.PutDocument(putDocumentOptions) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | b, _ := json.MarshalIndent(documentResult, "", " ") 35 | fmt.Println(string(b)) 36 | -------------------------------------------------------------------------------- /examples/snippets/putLocalDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | localDocument := cloudantv1.Document{} 17 | properties := map[string]interface{}{ 18 | "type": "order", 19 | "user": "Bob Smith", 20 | "orderId": "0007741142412418284", 21 | "userId": "abc123", 22 | "total": 214.98, 23 | "deliveryAddress": "19 Front Street, Darlington, DL5 1TY", 24 | "delivered": true, 25 | "courier": "UPS", 26 | "courierId": "15125425151261289", 27 | "date": "2019-01-28T10:44:22.000Z", 28 | } 29 | for key, value := range properties { 30 | localDocument.SetProperty(key, value) 31 | } 32 | 33 | putLocalDocumentOptions := service.NewPutLocalDocumentOptions( 34 | "orders", 35 | "local-0007741142412418284", 36 | ) 37 | putLocalDocumentOptions.SetDocument(&localDocument) 38 | 39 | documentResult, response, err := service.PutLocalDocument(putLocalDocumentOptions) 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | b, _ := json.MarshalIndent(documentResult, "", " ") 45 | fmt.Println(string(b)) 46 | -------------------------------------------------------------------------------- /examples/snippets/putReplicationDocument/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | "github.com/IBM/go-sdk-core/v5/core" 8 | ) 9 | // section: code 10 | service, err := cloudantv1.NewCloudantV1( 11 | &cloudantv1.CloudantV1Options{}, 12 | ) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | source, err := service.NewReplicationDatabase( 18 | "/animaldb", 19 | ) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | target, err := service.NewReplicationDatabase( 25 | "/animaldb-target", 26 | ) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | auth, err := service.NewReplicationDatabaseAuthIam( 32 | "", 33 | ) 34 | if err != nil { 35 | panic(err) 36 | } 37 | target.Auth = &cloudantv1.ReplicationDatabaseAuth{Iam: auth} 38 | 39 | replicationDoc, err := service.NewReplicationDocument( 40 | source, 41 | target, 42 | ) 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | replicationDoc.CreateTarget = core.BoolPtr(true) 48 | 49 | putReplicationDocumentOptions := service.NewPutReplicationDocumentOptions( 50 | "repldoc-example", 51 | replicationDoc, 52 | ) 53 | 54 | documentResult, response, err := service.PutReplicationDocument(putReplicationDocumentOptions) 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | b, _ := json.MarshalIndent(documentResult, "", " ") 60 | fmt.Println(string(b)) 61 | -------------------------------------------------------------------------------- /examples/snippets/putSecurity/example_request.go: -------------------------------------------------------------------------------- 1 | // section: code imports 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | 6 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 7 | ) 8 | // section: code 9 | service, err := cloudantv1.NewCloudantV1( 10 | &cloudantv1.CloudantV1Options{}, 11 | ) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | putSecurityOptions := service.NewPutSecurityOptions( 17 | "products", 18 | ) 19 | putSecurityOptions.SetMembers(&cloudantv1.SecurityObject{ 20 | Names: []string{"user1", "user2"}, 21 | Roles: []string{"developers"}, 22 | }) 23 | 24 | ok, response, err := service.PutSecurity(putSecurityOptions) 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | b, _ := json.MarshalIndent(ok, "", " ") 30 | fmt.Println(string(b)) 31 | // section: markdown 32 | // The `nobody` username applies to all unauthenticated connection attempts. For example, if an application tries to read data from a database, but didn't identify itself, the task can continue only if the `nobody` user has the role `_reader`. 33 | // section: markdown 34 | // If instead of using Cloudant's security model for managing permissions you opt to use the Apache CouchDB `_users` database (that is using legacy credentials _and_ the `couchdb_auth_only:true` option) then be aware that the user must already exist in `_users` database before adding permissions. For information on the `_users` database, see Using the `_users` database with Cloudant. 35 | -------------------------------------------------------------------------------- /features/changes_follower_suite_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2022, 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package features 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestChangesFollower(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "ChangesFollower Suite") 29 | } 30 | -------------------------------------------------------------------------------- /features/changes_follower_test_fixtures_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2022, 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package features 18 | 19 | import ( 20 | "context" 21 | "encoding/json" 22 | "fmt" 23 | "math" 24 | "net/http" 25 | "net/http/httptest" 26 | "strconv" 27 | "sync/atomic" 28 | "time" 29 | 30 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 31 | "github.com/IBM/go-sdk-core/v5/core" 32 | 33 | . "github.com/onsi/ginkgo" 34 | . "github.com/onsi/gomega" 35 | ) 36 | 37 | const ( 38 | maxBatches = math.MaxInt / BatchSize 39 | StatusBrokenJson = 600 40 | StatusBadIO = 601 41 | ) 42 | 43 | var noErrors []int = []int{} 44 | 45 | var transientErrors []int = []int{ 46 | http.StatusTooManyRequests, 47 | http.StatusInternalServerError, 48 | http.StatusBadGateway, 49 | http.StatusGatewayTimeout, 50 | StatusBrokenJson, 51 | StatusBadIO, 52 | } 53 | 54 | var terminalErrors []int = []int{ 55 | http.StatusBadRequest, 56 | http.StatusUnauthorized, 57 | http.StatusForbidden, 58 | http.StatusNotFound, 59 | } 60 | 61 | var limits []int = []int{ 62 | 100, 63 | BatchSize, 64 | BatchSize + 123, 65 | } 66 | 67 | type MockGenerator interface { 68 | Next() (statusCode int, data []byte) 69 | } 70 | 71 | type MockChangesGenerator struct { 72 | batches int 73 | errs []int 74 | batchNum int 75 | returnError bool 76 | } 77 | 78 | func NewMockChangesGenerator(batches int, errs []int) *MockChangesGenerator { 79 | return &MockChangesGenerator{ 80 | batchNum: 1, 81 | returnError: false, 82 | batches: batches, 83 | errs: errs, 84 | } 85 | } 86 | 87 | func (mg *MockChangesGenerator) Next() (statusCode int, data []byte) { 88 | if mg.returnError { 89 | mg.returnError = false 90 | switch err := mg.errs[(mg.batchNum)%len(mg.errs)]; err { 91 | case StatusBrokenJson: 92 | return http.StatusOK, []byte(`{`) 93 | default: 94 | return err, []byte{} 95 | } 96 | } 97 | // this stands for "large" seq in empty result case 98 | final := mg.batches * BatchSize 99 | lastSeq := fmt.Sprintf("%d-abcdef", final) 100 | pending := 0 101 | results := make([]cloudantv1.ChangesResultItem, 0) 102 | if mg.batchNum <= mg.batches { 103 | // we start from doc idx 000001 104 | start := (mg.batchNum-1)*BatchSize + 1 105 | stop := start + BatchSize 106 | lastSeq = fmt.Sprintf("%d-abcdef", stop-1) 107 | pending = mg.batches*BatchSize - mg.batchNum*BatchSize 108 | for idx := start; idx < stop; idx++ { 109 | id := fmt.Sprintf("%06d", idx) 110 | seq := fmt.Sprintf("%d-abcdef", idx) 111 | results = append(results, cloudantv1.ChangesResultItem{ 112 | ID: core.StringPtr(id), 113 | Changes: make([]cloudantv1.Change, 0), 114 | Seq: core.StringPtr(seq), 115 | }) 116 | } 117 | } 118 | mg.batchNum += 1 119 | if len(mg.errs) > 0 { 120 | mg.returnError = true 121 | } 122 | data, err := json.Marshal(cloudantv1.ChangesResult{ 123 | LastSeq: core.StringPtr(lastSeq), 124 | Pending: core.Int64Ptr(int64(pending)), 125 | Results: results, 126 | }) 127 | Expect(err).ShouldNot(HaveOccurred()) 128 | 129 | return http.StatusOK, data 130 | } 131 | 132 | type MockErrorGenerator struct { 133 | err int 134 | data []byte 135 | } 136 | 137 | func NewMockErrorGenerator(err int) *MockErrorGenerator { 138 | switch err { 139 | case StatusBrokenJson: 140 | return &MockErrorGenerator{err: http.StatusOK, data: []byte(`{`)} 141 | default: 142 | return &MockErrorGenerator{err: err, data: []byte{}} 143 | } 144 | } 145 | 146 | func (mg *MockErrorGenerator) Next() (statusCode int, data []byte) { 147 | return mg.err, mg.data 148 | } 149 | 150 | type MockDbInfoGenerator struct { 151 | resp []byte 152 | } 153 | 154 | func NewDbInfoGenerator(docCount, docSize int) *MockDbInfoGenerator { 155 | data, err := json.Marshal(map[string]interface{}{ 156 | "doc_count": docCount, 157 | "sizes": map[string]int{ 158 | "external": docCount * docSize, 159 | }, 160 | }) 161 | Expect(err).ShouldNot(HaveOccurred()) 162 | 163 | return &MockDbInfoGenerator{resp: data} 164 | } 165 | 166 | func (mg *MockDbInfoGenerator) Next() (statusCode int, data []byte) { 167 | return http.StatusOK, mg.resp 168 | } 169 | 170 | type MockServer struct { 171 | server *httptest.Server 172 | mockGenerator MockGenerator 173 | dbInfo MockGenerator 174 | callNumber atomic.Int32 175 | limit atomic.Int32 176 | } 177 | 178 | func NewMockServer(batches int, errs []int) *MockServer { 179 | mg := NewMockChangesGenerator(batches, errs) 180 | ms := MockServer{mockGenerator: mg} 181 | ms.callNumber.Store(0) 182 | return &ms 183 | } 184 | 185 | func NewMockErrorServer(err int) *MockServer { 186 | mg := NewMockErrorGenerator(err) 187 | ms := MockServer{mockGenerator: mg} 188 | ms.callNumber.Store(0) 189 | ms.limit.Store(0) 190 | return &ms 191 | } 192 | 193 | func (ms *MockServer) WithDbInfo(docCount, docSize int) *MockServer { 194 | ms.dbInfo = NewDbInfoGenerator(docCount, docSize) 195 | return ms 196 | } 197 | 198 | func (ms *MockServer) WithDbInfoError(err int) *MockServer { 199 | ms.dbInfo = NewMockErrorGenerator(err) 200 | return ms 201 | } 202 | 203 | func (ms *MockServer) Start() *cloudantv1.CloudantV1 { 204 | ms.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 205 | defer GinkgoRecover() 206 | 207 | var statusCode int 208 | var data []byte 209 | switch path := r.URL.EscapedPath(); path { 210 | case "/db": 211 | Expect(r.Method).To(Equal("GET")) 212 | statusCode, data = ms.dbInfo.Next() 213 | default: 214 | postChangesPath := "/db/_changes" 215 | Expect(path).To(Equal(postChangesPath)) 216 | Expect(r.Method).To(Equal("POST")) 217 | statusCode, data = ms.mockGenerator.Next() 218 | if statusCode == StatusBadIO { 219 | // return header and shut down the connection to get 220 | // "An error occurred while reading the response body: EOF" 221 | ms.callNumber.Add(1) 222 | w.WriteHeader(statusCode) 223 | hj, ok := w.(http.Hijacker) 224 | if !ok { 225 | http.Error(w, "can't create hijack rw", http.StatusInternalServerError) 226 | return 227 | } 228 | conn, _, err := hj.Hijack() 229 | if err != nil { 230 | http.Error(w, err.Error(), http.StatusInternalServerError) 231 | return 232 | } 233 | err = conn.Close() 234 | if err != nil { 235 | http.Error(w, err.Error(), http.StatusInternalServerError) 236 | return 237 | } 238 | return 239 | } 240 | 241 | l, err := strconv.ParseUint(r.URL.Query().Get("limit"), 10, 32) 242 | Expect(err).ShouldNot(HaveOccurred()) 243 | ms.limit.Store(int32(l)) 244 | } 245 | // Set mock response 246 | w.Header().Set("content-type", "application/json") 247 | w.WriteHeader(statusCode) 248 | //nolint:errcheck 249 | w.Write(data) 250 | 251 | ms.callNumber.Add(1) 252 | })) 253 | 254 | service, serviceErr := cloudantv1.NewCloudantV1(&cloudantv1.CloudantV1Options{ 255 | URL: ms.server.URL, 256 | Authenticator: &core.NoAuthAuthenticator{}, 257 | }) 258 | Expect(serviceErr).ShouldNot(HaveOccurred()) 259 | Expect(service).ToNot(BeNil()) 260 | 261 | return service 262 | } 263 | 264 | func (ms *MockServer) Limit() int { 265 | return int(ms.limit.Load()) 266 | } 267 | 268 | func (ms *MockServer) CallNumber() int { 269 | return int(ms.callNumber.Load()) 270 | } 271 | 272 | func (ms *MockServer) Stop() { 273 | ms.server.Close() 274 | } 275 | 276 | func ErrorText(err int) string { 277 | switch err { 278 | case StatusBrokenJson: 279 | return "An error occurred while processing the HTTP response" 280 | default: 281 | return http.StatusText(err) 282 | } 283 | } 284 | 285 | type runnerConfig struct { 286 | mode Mode 287 | timeout time.Duration 288 | stopAfter int 289 | } 290 | 291 | func runner(cf *ChangesFollower, c runnerConfig) (int, error) { 292 | ctx, cancel := context.WithTimeout(context.Background(), c.timeout) 293 | defer cancel() 294 | countCh := make(chan int) 295 | errors := make(chan error) 296 | go func() { 297 | defer GinkgoRecover() 298 | defer close(countCh) 299 | defer close(errors) 300 | count := 0 301 | var changesCh <-chan ChangesItem 302 | var err error 303 | switch c.mode { 304 | case Finite: 305 | changesCh, err = cf.StartOneOff() 306 | case Listen: 307 | changesCh, err = cf.Start() 308 | } 309 | Expect(err).ShouldNot(HaveOccurred()) 310 | Expect(changesCh).ToNot(BeNil()) 311 | for { 312 | select { 313 | case <-ctx.Done(): 314 | cf.Stop() 315 | // check that changesCh was closed 316 | select { 317 | case <-changesCh: 318 | default: 319 | } 320 | // return last count 321 | countCh <- count 322 | return 323 | case ci, ok := <-changesCh: 324 | // Follower quit and closed the changes channel 325 | if !ok || (c.stopAfter > 0 && count > c.stopAfter) { 326 | countCh <- count 327 | return 328 | } 329 | item, err := ci.Item() 330 | if err != nil { 331 | errors <- err 332 | return 333 | } 334 | Expect(item).ToNot(Equal(cloudantv1.ChangesResultItem{})) 335 | count += 1 336 | } 337 | } 338 | }() 339 | select { 340 | case error := <-errors: 341 | return 0, error 342 | case count := <-countCh: 343 | return count, nil 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/IBM/cloudant-go-sdk 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.24.1 6 | 7 | require ( 8 | github.com/IBM/go-sdk-core/v5 v5.20.0 9 | github.com/go-openapi/strfmt v0.23.0 10 | github.com/onsi/ginkgo v1.16.5 11 | github.com/onsi/gomega v1.37.0 12 | golang.org/x/net v0.41.0 13 | ) 14 | 15 | require ( 16 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect 17 | github.com/fsnotify/fsnotify v1.6.0 // indirect 18 | github.com/gabriel-vasile/mimetype v1.4.8 // indirect 19 | github.com/go-openapi/errors v0.22.0 // indirect 20 | github.com/go-playground/locales v0.14.1 // indirect 21 | github.com/go-playground/universal-translator v0.18.1 // indirect 22 | github.com/go-playground/validator/v10 v10.26.0 // indirect 23 | github.com/google/go-cmp v0.7.0 // indirect 24 | github.com/google/uuid v1.6.0 // indirect 25 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 26 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 27 | github.com/leodido/go-urn v1.4.0 // indirect 28 | github.com/mitchellh/mapstructure v1.5.0 // indirect 29 | github.com/nxadm/tail v1.4.8 // indirect 30 | github.com/oklog/ulid v1.3.1 // indirect 31 | go.mongodb.org/mongo-driver v1.17.2 // indirect 32 | golang.org/x/crypto v0.39.0 // indirect 33 | golang.org/x/sys v0.33.0 // indirect 34 | golang.org/x/text v0.26.0 // indirect 35 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 36 | gopkg.in/yaml.v3 v3.0.1 // indirect 37 | sigs.k8s.io/yaml v1.4.0 // indirect 38 | ) 39 | -------------------------------------------------------------------------------- /scripts/publish_buildinfo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ev 4 | file="/tmp/build.json" 5 | tmpfile="/tmp/build.json.tmp" 6 | printf "Current values set:\n Module ID: $MODULE_ID\nBuild name: $BUILD_NAME\nBuild URL: $BUILD_URL\nBuild timestamp: $BUILD_TIMESTAMP\nBuild number: $BUILD_NUMBER\n" 7 | printf "Artifactory URL: $ARTIFACT_URL\n" 8 | ARTIFACTS=$(curl -f -H "Authorization: Bearer $ARTIFACTORY_CREDS_PSW" "$ARTIFACT_URL") 9 | HAS_CHILDREN_RESULT=$(echo $ARTIFACTS | jq 'has("children")') 10 | # if 'children' array exists then grab all aritfact uris, else grab parent uri 11 | if [[ "$HAS_CHILDREN_RESULT" == "false" ]]; then 12 | ARTIFACTS_URI=$(echo $ARTIFACTS | jq -r '.uri' | sed 's:.*/:/:') 13 | else 14 | ARTIFACTS_URI=$(echo $ARTIFACTS | jq -r '.children[] | .uri') 15 | fi 16 | 17 | if [[ -z $ARTIFACTS_URI || -z $MODULE_ID || -z $BUILD_NAME || -z $BUILD_URL || -z $BUILD_TIMESTAMP || -z $BUILD_NUMBER ]]; then 18 | printf "one or more variables are undefined. Check printed statement above." 19 | exit 1 20 | fi 21 | 22 | # create new (or write over existing) build.json file 23 | echo -n "" > $file 24 | # get current published build 25 | CURRENT_BUILD=$(curl -f -H "Authorization: Bearer $ARTIFACTORY_CREDS_PSW" "$STAGE_ROOT"build/"$BUILD_NAME"/"$BUILD_NUMBER") 26 | echo $CURRENT_BUILD 27 | CURRENT_BUILD_INFO=$(echo "$CURRENT_BUILD" | jq -r '.buildInfo') 28 | echo $CURRENT_BUILD_INFO | tee $file 29 | 30 | # put build name, number, and url on published artifacts 31 | URL_WITH_PROPS="$ARTIFACT_URL?properties=build.name=$BUILD_NAME;build.number=$BUILD_NUMBER;build.url=$BUILD_URL" 32 | curl --fail-with-body -i -X PUT -H "Authorization: Bearer $ARTIFACTORY_CREDS_PSW" "$URL_WITH_PROPS" 33 | 34 | # add artifact type and module id to build info file 35 | jq --arg type "$TYPE" '.type = $type' $file > $tmpfile && mv $tmpfile $file 36 | jq --arg id "$MODULE_ID" '.modules[0].id = $id' $file > $tmpfile && mv $tmpfile $file 37 | 38 | # get md5 and sha1 from each artifact and add to build info file 39 | for artifact in $ARTIFACTS_URI; do 40 | # node does not have 'children' artifacts 41 | if [[ "$HAS_CHILDREN_RESULT" == "false" ]]; then 42 | ARTIFACT_INFO_URL="$ARTIFACT_URL" 43 | else 44 | ARTIFACT_INFO_URL="$ARTIFACT_URL$artifact" 45 | fi 46 | GET_ARTIFACT=$(curl -f -H "Authorization: Bearer $ARTIFACTORY_CREDS_PSW" $ARTIFACT_INFO_URL | jq -r .checksums) 47 | MD5=$(echo $GET_ARTIFACT | jq -r .md5) 48 | SHA1=$(echo $GET_ARTIFACT | jq -r .sha1) 49 | NAME="${artifact#*/}" 50 | jq --arg name "$NAME" --arg md5 "$MD5" --arg sha1 "$SHA1" '.modules[0].artifacts += [{"name": $name, "md5": $md5, "sha1": $sha1}]' $file > $tmpfile && mv $tmpfile $file 51 | done 52 | 53 | if jq empty $file 2>/dev/null; then 54 | echo "JSON in $file is valid" 55 | else 56 | echo "JSON in $file is invalid" 57 | exit 1 58 | fi 59 | 60 | curl --fail-with-body -i -X PUT -H "Authorization: Bearer $ARTIFACTORY_CREDS_PSW" -H "Content-Type: application/json" "$STAGE_ROOT"build --upload-file $file 61 | -------------------------------------------------------------------------------- /scripts/setup_couch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ev 4 | 5 | printenv | grep "^SERVER_" >> cloudant_v1.env 6 | # if you change the image version please regenerate example output captures 7 | # use image at ARTIFACTORY_DOCKER_REPO_VIRTUAL registry if set, otherwise use default registry 8 | 9 | # shellcheck disable=SC2016 10 | timeout 120 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' ${SERVER_URL}/_up)" != "200" ]]; do sleep 5; done' || false 11 | curl -XPUT -u "$SERVER_USERNAME":"$SERVER_PASSWORD" "$SERVER_URL"/_users 12 | curl -XPUT -u "$SERVER_USERNAME":"$SERVER_PASSWORD" "$SERVER_URL"/stores 13 | curl -XPOST -u "$SERVER_USERNAME":"$SERVER_PASSWORD" -H "Content-type: application/json" -d '{}' "$SERVER_URL"/stores 14 | -------------------------------------------------------------------------------- /scripts/setup_wiremock.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ev 4 | 5 | printenv | grep "^WIREMOCK_" > wiremock.env 6 | # setup env file for gen ITs 7 | echo -e "CLOUDANT_AUTH_TYPE=noauth\nCLOUDANT_URL=$WIREMOCK_URL" >> cloudant_v1.env 8 | 9 | # use image at ARTIFACTORY_DOCKER_REPO_VIRTUAL registry if set, otherwise use default registry 10 | timeout 120 bash -c 'while [[ "$(curl -s --location -o /dev/null -w ''%{http_code}'' ${WIREMOCK_URL}/__admin)" != "200" ]]; do sleep 2; done' || false 11 | curl "$WIREMOCK_URL"/__admin/mappings/import -X POST -d @stubs/mappings.json 12 | curl "$WIREMOCK_URL"/__admin/mappings/import -X POST -d @stubs/gen-its-mappings.json 13 | echo "Wiremock started" 14 | -------------------------------------------------------------------------------- /test/examples/output/create_db_and_doc.txt: -------------------------------------------------------------------------------- 1 | "orders" database created. 2 | You have created the document: 3 | { 4 | "_id": "example", 5 | "_rev": "1-1b403633540686aa32d013fda9041a5d", 6 | "joined": "2019-01-24T10:42:99.000Z", 7 | "name": "Bob Smith" 8 | } -------------------------------------------------------------------------------- /test/examples/output/delete_doc.txt: -------------------------------------------------------------------------------- 1 | You have deleted the document. -------------------------------------------------------------------------------- /test/examples/output/get_info_from_existing_database.txt: -------------------------------------------------------------------------------- 1 | Server Version: 2.1.1 2 | Document count in "orders" database is 1. 3 | { 4 | "_id": "example", 5 | "_rev": "1-1b403633540686aa32d013fda9041a5d", 6 | "name": "Bob Smith", 7 | "joined": "2019-01-24T10:42:99.000Z" 8 | } -------------------------------------------------------------------------------- /test/examples/output/update_doc.txt: -------------------------------------------------------------------------------- 1 | You have updated the document: 2 | { 3 | "_id": "example", 4 | "_rev": "2-4e2178e85cffb32d38ba4e451f6ca376", 5 | "address": "19 Front Street, Darlington, DL5 1TY", 6 | "name": "Bob Smith" 7 | } -------------------------------------------------------------------------------- /test/examples/src/changes_follower/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/IBM/cloudant-go-sdk/examples/changes_follower 2 | 3 | go 1.22.5 4 | -------------------------------------------------------------------------------- /test/examples/src/changes_follower/initialize.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "time" 21 | 22 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 23 | "github.com/IBM/cloudant-go-sdk/features" 24 | ) 25 | 26 | func main() { 27 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 28 | &cloudantv1.CloudantV1Options{}, 29 | ) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | // Required: the database name. 35 | postChangesOptions := client.NewPostChangesOptions("example") 36 | 37 | // Optional: return only 100 changes (including duplicates). 38 | postChangesOptions.SetLimit(100) 39 | 40 | // Optional: start from this sequence ID (e.g. with a value read from persistent storage). 41 | postChangesOptions.SetSince("3-g1AG3...") 42 | 43 | // Required: the Cloudant service client instance and an instance of PostChangesOptions 44 | follower, err := features.NewChangesFollower(client, postChangesOptions) 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | // Optional: suppress transient errors for at least 10 seconds before terminating. 50 | err = follower.SetErrorTolerance(10 * time.Second) 51 | if err != nil { 52 | panic(err) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/examples/src/changes_follower/start.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 21 | "github.com/IBM/cloudant-go-sdk/features" 22 | ) 23 | 24 | func main() { 25 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 26 | &cloudantv1.CloudantV1Options{}, 27 | ) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | postChangesOptions := client.NewPostChangesOptions("example") 33 | 34 | follower, err := features.NewChangesFollower(client, postChangesOptions) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | changesCh, err := follower.Start() 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | // Note: changesCh channel will not do anything until it is read from. 45 | // Create a range loop to iterate over the flow of the changes items 46 | } 47 | -------------------------------------------------------------------------------- /test/examples/src/changes_follower/start_and_process.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 23 | "github.com/IBM/cloudant-go-sdk/features" 24 | ) 25 | 26 | func main() { 27 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 28 | &cloudantv1.CloudantV1Options{}, 29 | ) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | postChangesOptions := client.NewPostChangesOptions("example") 35 | 36 | // Start from a previously persisted seq 37 | // Normally this would be read by the app from persistent storage 38 | // e.g. prevSeq = yourAppPersistenceReadFunc() 39 | prevSeq := "3-g1AG3..." 40 | postChangesOptions.SetSince(prevSeq) 41 | 42 | follower, err := features.NewChangesFollower(client, postChangesOptions) 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | changesCh, err := follower.Start() 48 | if err != nil { 49 | panic(err) 50 | } 51 | 52 | for changesItem := range changesCh { 53 | // changes item returns an error on failed requests 54 | item, err := changesItem.Item() 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | // do something with changes 60 | fmt.Printf("%s\n", *item.ID) 61 | for _, change := range item.Changes { 62 | fmt.Printf("%s\n", *change.Rev) 63 | } 64 | 65 | // when change item processing is complete app can store seq 66 | seq := *item.Seq 67 | // write seq to persistent storage for use as since 68 | // if required to resume later, e.g. yourAppPersistenceWriteFunc(seq) 69 | // keep processing changes until the application is terminated 70 | // or some other stop condition is reached 71 | } 72 | 73 | // Note: the returned channel continues to listen for changes 74 | // indefinitely. In other words iterating it is blocking, 75 | // code here will be unreachable until break from the range 76 | // or another stop condition is reached. 77 | // For long running followers careful consideration 78 | // should be made of where to call stop on the follower. 79 | } 80 | -------------------------------------------------------------------------------- /test/examples/src/changes_follower/start_one_off.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 21 | "github.com/IBM/cloudant-go-sdk/features" 22 | ) 23 | 24 | func main() { 25 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 26 | &cloudantv1.CloudantV1Options{}, 27 | ) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | postChangesOptions := client.NewPostChangesOptions("example") 33 | 34 | follower, err := features.NewChangesFollower(client, postChangesOptions) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | changesCh, err = follower.StartOneOff() 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | // Note: the returned channel will not do anything until it is read 45 | // Create a range loop to iterate over the flow of the change items 46 | } 47 | -------------------------------------------------------------------------------- /test/examples/src/changes_follower/start_one_off_and_process.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 23 | "github.com/IBM/cloudant-go-sdk/features" 24 | ) 25 | 26 | func main() { 27 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 28 | &cloudantv1.CloudantV1Options{}, 29 | ) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | postChangesOptions := client.NewPostChangesOptions("example") 35 | 36 | // Start from a previously persisted seq 37 | // Normally this would be read by the app from persistent storage 38 | // e.g. prevSeq = yourAppPersistenceReadFunc() 39 | prevSeq := "3-g1AG3..." 40 | postChangesOptions.SetSince(prevSeq) 41 | 42 | follower, err := features.NewChangesFollower(client, postChangesOptions) 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | changesCh, err := follower.StartOneOff() 48 | if err != nil { 49 | panic(err) 50 | } 51 | 52 | for changesItem := range changesCh { 53 | // changes item structure returns an error on failed requests 54 | item, err := changesItem.Item() 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | // do something with changes 60 | fmt.Printf("%s\n", *item.ID) 61 | for _, change := range item.Changes { 62 | fmt.Printf("%s\n", *change.Rev) 63 | } 64 | 65 | // when change item processing is complete app can store seq 66 | seq := *item.Seq 67 | // write seq to persistent storage for use as since if required 68 | // to resume later, e.g. yourAppPersistenceWriteFunc(seq) 69 | } 70 | 71 | // Note: iterating the returned channel above is blocking, code here 72 | // will be unreachable until all changes are processed 73 | // or another stop condition is reached. 74 | } 75 | -------------------------------------------------------------------------------- /test/examples/src/changes_follower/stop.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2023. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 23 | "github.com/IBM/cloudant-go-sdk/features" 24 | ) 25 | 26 | func main() { 27 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 28 | &cloudantv1.CloudantV1Options{}, 29 | ) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | postChangesOptions := client.NewPostChangesOptions("example") 35 | 36 | ctx, cancel := context.WithCancel(context.Background()) 37 | // Option 1: call cancel function when ChangesFollower created 38 | // with a cancellable context. 39 | // Note that this is a good practice to always call cancel function, 40 | // e.g. in defer to prevent possible goroutine leak. 41 | defer cancel() 42 | follower, err := features.NewChangesFollowerWithContext(ctx, client, postChangesOptions) 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | changesCh, err := follower.Start() 48 | if err != nil { 49 | panic(err) 50 | } 51 | 52 | for changesItem := range changesCh { 53 | // changes item structure returns an error on failed requests 54 | if changesItem.Error != nil { 55 | panic(changesItem.Error) 56 | } 57 | 58 | // Option 2: call stop after some condition 59 | // Note that at least one item must be returned from the channel 60 | // to reach this point. Additional changes may be processed 61 | // before the channel quits. 62 | follower.Stop() 63 | } 64 | 65 | // Option 3: call stop method when you want to end the continuous loop from 66 | // outside the channel. For example, you've put the changes follower in a 67 | // goroutine and need to call stop on the main goroutine. 68 | // Note: in this context the call must be made from a different 69 | // goroutine because code immediately following the range is unreachable 70 | // until the channel has quit. 71 | follower.Stop() 72 | } 73 | -------------------------------------------------------------------------------- /test/examples/src/create_db_and_doc/create_db_and_doc.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2022. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "encoding/json" 21 | "fmt" 22 | 23 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 24 | ) 25 | 26 | func main() { 27 | // 1. Create a client with `CLOUDANT` default service name ============= 28 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 29 | &cloudantv1.CloudantV1Options{}, 30 | ) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | // 2. Create a database ================================================ 36 | exampleDbName := "orders" 37 | 38 | putDatabaseResult, putDatabaseResponse, err := client.PutDatabase( 39 | client.NewPutDatabaseOptions(exampleDbName), 40 | ) 41 | if err != nil { 42 | if putDatabaseResponse.StatusCode == 412 { 43 | fmt.Printf("Cannot create \"%s\" database, it already exists.\n", 44 | exampleDbName) 45 | } else { 46 | panic(err) 47 | } 48 | } 49 | 50 | if putDatabaseResult != nil && *putDatabaseResult.Ok { 51 | fmt.Printf("\"%s\" database created.\n", exampleDbName) 52 | } 53 | 54 | // 3. Create a document ================================================ 55 | // Create a document object with "example" id 56 | exampleDocID := "example" 57 | // Setting ID for the document is optional when "PostDocument" function 58 | // is used for CREATE. 59 | // When ID is not provided the server will generate one for your document. 60 | exampleDocument := cloudantv1.Document{ 61 | ID: &exampleDocID, 62 | } 63 | 64 | // Add "name" and "joined" fields to the document 65 | exampleDocument.SetProperty("name", "Bob Smith") 66 | exampleDocument.SetProperty("joined", "2019-01-24T10:42:59.000Z") 67 | 68 | // Save the document in the database with "PostDocument" function 69 | createDocumentOptions := client.NewPostDocumentOptions( 70 | exampleDbName, 71 | ).SetDocument(&exampleDocument) 72 | 73 | createDocumentResponse, _, err := client.PostDocument(createDocumentOptions) 74 | 75 | // ===================================================================== 76 | // Note: saving the document can also be done with the "PutDocument" 77 | // function. In this case docID is required for a CREATE operation: 78 | /* 79 | createDocumentOptions := client.NewPutDocumentOptions( 80 | exampleDbName, 81 | exampleDocID, 82 | ).SetDocument(&exampleDocument) 83 | 84 | createDocumentResponse, _, err := client.PutDocument(createDocumentOptions) 85 | */ 86 | // ===================================================================== 87 | 88 | if err != nil { 89 | panic(err) 90 | } 91 | 92 | // Keeping track of the revision number of the document object 93 | // is necessary for further UPDATE/DELETE operations: 94 | exampleDocument.Rev = createDocumentResponse.Rev 95 | 96 | // Print out the document content 97 | exampleDocumentContent, _ := json.MarshalIndent(exampleDocument, "", " ") 98 | fmt.Printf("You have created the document:\n%s\n", string(exampleDocumentContent)) 99 | } 100 | -------------------------------------------------------------------------------- /test/examples/src/delete_doc/delete_doc.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2022. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 23 | ) 24 | 25 | func main() { 26 | 27 | // 1. Create a client with `CLOUDANT` default service name ============= 28 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 29 | &cloudantv1.CloudantV1Options{}, 30 | ) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | // 2. Delete the document ============================================== 36 | exampleDbName := "orders" 37 | exampleDocID := "example" 38 | 39 | // 2.1. Get the document if it previously existed in the database 40 | document, getDocumentResponse, err := client.GetDocument( 41 | client.NewGetDocumentOptions( 42 | exampleDbName, 43 | exampleDocID, 44 | ), 45 | ) 46 | if err != nil { 47 | if getDocumentResponse.StatusCode == 404 { 48 | fmt.Printf("Cannot delete document because "+ 49 | "either \"%s\" database or \"%s\" document was not found.\n", 50 | exampleDbName, 51 | exampleDocID) 52 | } else { 53 | panic(err) 54 | } 55 | } 56 | // 2.2. Use its latest revision to delete 57 | if document != nil { 58 | deleteDocumentResult, _, err := client.DeleteDocument( 59 | client.NewDeleteDocumentOptions( 60 | exampleDbName, 61 | *document.ID, // docID is required for DELETE 62 | ).SetRev(*document.Rev), // Rev is required for DELETE 63 | ) 64 | if err != nil { 65 | panic(err) 66 | } 67 | 68 | if *deleteDocumentResult.Ok { 69 | fmt.Println("You have deleted the document.") 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/examples/src/get_info_from_existing_database/get_info_from_existing_database.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "encoding/json" 21 | "fmt" 22 | 23 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 24 | ) 25 | 26 | func main() { 27 | // 1. Create a client with `CLOUDANT` default service name ============ 28 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 29 | &cloudantv1.CloudantV1Options{}, 30 | ) 31 | if err != nil { 32 | panic(err) 33 | } 34 | // 2. Get server information =========================================== 35 | serverInformationResult, _, err := client.GetServerInformation( 36 | client.NewGetServerInformationOptions(), 37 | ) 38 | if err != nil { 39 | panic(err) 40 | } 41 | fmt.Printf("Server Version: %s\n", *serverInformationResult.Version) 42 | // 3. Get database information for "orders" ========================== 43 | dbName := "orders" 44 | databaseInformationResult, _, err := client.GetDatabaseInformation( 45 | client.NewGetDatabaseInformationOptions( 46 | dbName, 47 | ), 48 | ) 49 | if err != nil { 50 | panic(err) 51 | } 52 | // 4. Show document count in database ================================== 53 | fmt.Printf("Document count in \"%s\" database is %d.\n", 54 | *databaseInformationResult.DbName, 55 | *databaseInformationResult.DocCount) 56 | // 5. Get "example" document out of the database by document id ============ 57 | documentExampleResult, _, err := client.GetDocument( 58 | client.NewGetDocumentOptions( 59 | dbName, 60 | "example", 61 | ), 62 | ) 63 | if err != nil { 64 | panic(err) 65 | } 66 | // 6. Print out the Document content =================================== 67 | exampleBuffer, _ := json.MarshalIndent(documentExampleResult, "", " ") 68 | fmt.Println(string(exampleBuffer)) 69 | } 70 | -------------------------------------------------------------------------------- /test/examples/src/update_doc/update_doc.go: -------------------------------------------------------------------------------- 1 | /** 2 | * © Copyright IBM Corporation 2020, 2022. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "encoding/json" 21 | "fmt" 22 | 23 | "github.com/IBM/cloudant-go-sdk/cloudantv1" 24 | ) 25 | 26 | func main() { 27 | // 1. Create a client with `CLOUDANT` default service name ============= 28 | client, err := cloudantv1.NewCloudantV1UsingExternalConfig( 29 | &cloudantv1.CloudantV1Options{}, 30 | ) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | // 2. Update the document ============================================== 36 | exampleDbName := "orders" 37 | exampleDocID := "example" 38 | 39 | // Get the document if it previously existed in the database 40 | document, getDocumentResponse, err := client.GetDocument( 41 | client.NewGetDocumentOptions( 42 | exampleDbName, 43 | exampleDocID, 44 | ), 45 | ) 46 | 47 | // ===================================================================== 48 | // Note: for response byte stream use: 49 | /* 50 | documentAsByteStream, getDocumentResponse, err := client.GetDocumentAsStream( 51 | client.NewGetDocumentOptions( 52 | exampleDbName, 53 | exampleDocID, 54 | ), 55 | ) 56 | */ 57 | // ===================================================================== 58 | 59 | if err != nil { 60 | if getDocumentResponse.StatusCode == 404 { 61 | fmt.Printf("Cannot update document because "+ 62 | "either \"%s\" database or \"%s\" document was not found.\n", 63 | exampleDbName, 64 | exampleDocID) 65 | } else { 66 | panic(err) 67 | } 68 | } 69 | 70 | if document != nil { 71 | // Make some modification in the document content 72 | // Add Bob Smith's address to the document 73 | document.SetProperty("address", "19 Front Street, Darlington, DL5 1TY") 74 | // Remove the joined property from document object 75 | delete(document.GetProperties(), "joined") 76 | 77 | // Update the document in the database 78 | updateDocumentOptions := client.NewPostDocumentOptions( 79 | exampleDbName, 80 | ).SetDocument(document) 81 | 82 | // ================================================================= 83 | // Note: for request byte stream use: 84 | /* 85 | postDocumentOption := client.NewPostDocumentOptions( 86 | exampleDbName, 87 | ).SetBody(documentAsByteStream) 88 | */ 89 | // ================================================================= 90 | 91 | updateDocumentResponse, _, err := client.PostDocument( 92 | updateDocumentOptions, 93 | ) 94 | 95 | // ================================================================= 96 | // Note: updating the document can also be done with the "PutDocument" 97 | // function. DocID and Rev are required for an UPDATE operation 98 | // but Rev can be provided in the document object too: 99 | /* 100 | updateDocumentOptions := client.NewPutDocumentOptions( 101 | exampleDbName, 102 | core.StringNilMapper(document.ID), // docID is a required parameter 103 | ).SetDocument(document) // Rev in the document object CAN replace below SetRev 104 | 105 | updateDocumentOptions.SetRev(core.StringNilMapper(document.Rev)) 106 | 107 | updateDocumentResponse, _, err := client.PutDocument( 108 | updateDocumentOptions, 109 | ) 110 | */ 111 | // ================================================================= 112 | 113 | if err != nil { 114 | panic(err) 115 | } 116 | 117 | // Keeping track of the latest revision number of the document object 118 | // is necessary for further UPDATE/DELETE operations: 119 | document.Rev = updateDocumentResponse.Rev 120 | 121 | // Print out the new document content 122 | documentContent, _ := json.MarshalIndent(document, "", " ") 123 | fmt.Printf("You have updated the document:\n%s\n", string(documentContent)) 124 | } 125 | } 126 | --------------------------------------------------------------------------------